Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/composites/jfrog/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ runs:
if: success() && ${{ inputs.version }} != ''
shell: bash
run: |
jf rt bdi c --max-builds=5
jf rt bdi c --max-builds=5
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup go
uses: actions/setup-go@v5
with:
go-version: 1.21
go-version: 1.24

- name: Setup deps
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.22 as build
FROM golang:1.24 as build

WORKDIR /go/src/

Expand Down
6 changes: 3 additions & 3 deletions client/jwt/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"fmt"
"strings"

"github.com/golang-jwt/jwt"
"github.com/golang-jwt/jwt/v5"
)

// Base64Encode encodes a byte array to a base 64 string.
Expand All @@ -44,7 +44,7 @@ func CryptoHash(base string) string {

// DecodeToken decodes the non-secret part of the jwt token and extracts the associated claims.
// Note: this method does not verify the tokens validity, for this the corresponding endpoint of the iam service should be used.
func DecodeToken(token string) (*jwt.StandardClaims, error) {
func DecodeToken(token string) (*jwt.RegisteredClaims, error) {
s := strings.Split(token, ".")
if len(s) < 2 {
return nil, fmt.Errorf("token format is wrong")
Expand All @@ -53,7 +53,7 @@ func DecodeToken(token string) (*jwt.StandardClaims, error) {
if err != nil {
return nil, fmt.Errorf("could not decode token part")
}
m := new(jwt.StandardClaims)
m := new(jwt.RegisteredClaims)
err = json.Unmarshal(b, &m)
if err != nil {
return nil, fmt.Errorf("could not unmarshal claims")
Expand Down
14 changes: 7 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
module github.com/ingka-group/iam-proxy

go 1.21
go 1.24.1

require (
contrib.go.opencensus.io/exporter/ocagent v0.7.0
github.com/blendle/zapdriver v1.3.1
github.com/gin-contrib/zap v1.1.0
github.com/gin-gonic/gin v1.10.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
Expand Down Expand Up @@ -42,6 +41,7 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
Expand All @@ -59,11 +59,11 @@ require (
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
google.golang.org/api v0.158.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
Expand Down
24 changes: 12 additions & 12 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/api/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func TestHealth(t *testing.T) {
}

if diff := cmp.Diff(h, tt.want); diff != "" {
t.Errorf(diff)
t.Error(diff)
}
})
}
Expand Down
8 changes: 4 additions & 4 deletions internal/api/iam_end2end_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func TestClient_GenerateToken(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
srv, err := service.New(defaultConfig(tt.iam))
if err != nil {
t.Errorf(fmt.Sprintf("could not create service instance: %s", err.Error()))
t.Errorf("could not create service instance: %s", err.Error())
}

tt.args.cfg.Service = srv
Expand Down Expand Up @@ -193,7 +193,7 @@ func TestClient_ParseToken(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
srv, err := service.New(defaultConfig(tt.iam))
if err != nil {
t.Errorf(fmt.Sprintf("could not create service instance: %s", err.Error()))
t.Errorf("could not create service instance: %s", err.Error())
}

tt.args.cfg.Service = srv
Expand Down Expand Up @@ -306,7 +306,7 @@ func TestClient_IdentityToken(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
srv, err := service.New(defaultConfig(tt.iam))
if err != nil {
t.Errorf(fmt.Sprintf("could not create service instance: %s", err.Error()))
t.Errorf("could not create service instance: %s", err.Error())
}

tt.args.cfg.Service = srv
Expand Down Expand Up @@ -355,7 +355,7 @@ func TestClient_End2End(t *testing.T) {

srv, err := service.New(defaultConfig(cfg))
if err != nil {
t.Errorf(fmt.Sprintf("could not create service instance: %s", err.Error()))
t.Errorf("could not create service instance: %s", err.Error())
}

c, err := New(Config{
Expand Down
25 changes: 13 additions & 12 deletions internal/service/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ package service

import (
"context"
"errors"
"fmt"
"time"

"github.com/golang-jwt/jwt"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"

"github.com/ingka-group/iam-proxy/internal/models"
Expand All @@ -35,7 +36,7 @@ const (

// Claims defines the token claims.
type Claims struct {
jwt.StandardClaims
jwt.RegisteredClaims
}

// verifyUser checks the iam privileges for the given client id and secret.
Expand Down Expand Up @@ -65,18 +66,18 @@ func (s *Service) GenerateToken(_ context.Context, clientID, clientSecret string
return "", "", 0, fmt.Errorf("user not authorized to use iam service: %w", err)
}

expiration := time.Now().Add(expirationInterval).Unix()
expiration := time.Now().Add(expirationInterval)

accessToken, err := s.createToken(&jwt.StandardClaims{
Id: uuid.New().String(),
ExpiresAt: expiration,
accessToken, err := s.createToken(&jwt.RegisteredClaims{
ID: uuid.New().String(),
ExpiresAt: jwt.NewNumericDate(expiration),
Issuer: issuer,
})
if err != nil {
return "", "", 0, fmt.Errorf("could not generate access token for %s: %w", appName, err)
}

identityToken, err := s.createToken(&jwt.StandardClaims{
identityToken, err := s.createToken(&jwt.RegisteredClaims{
Issuer: issuer,
Subject: appName,
})
Expand All @@ -87,7 +88,7 @@ func (s *Service) GenerateToken(_ context.Context, clientID, clientSecret string
return accessToken, identityToken, int64(expirationInterval.Seconds()), nil
}

func (s *Service) createToken(claims *jwt.StandardClaims) (string, error) {
func (s *Service) createToken(claims *jwt.RegisteredClaims) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
tokenString, err := token.SignedString(s.secret)
if err != nil {
Expand All @@ -98,7 +99,7 @@ func (s *Service) createToken(claims *jwt.StandardClaims) (string, error) {

// ParseToken parses the token and confirms its validity.
func (s *Service) ParseToken(tokenString string) (string, error) {
token, err := jwt.ParseWithClaims(tokenString, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
token, err := jwt.ParseWithClaims(tokenString, &jwt.RegisteredClaims{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
Expand All @@ -109,12 +110,12 @@ func (s *Service) ParseToken(tokenString string) (string, error) {
return "", fmt.Errorf("%s: %w", parseTokenError, err)
}

if claims, ok := token.Claims.(*jwt.StandardClaims); ok && token.Valid {
if claims, ok := token.Claims.(*jwt.RegisteredClaims); ok && token.Valid {
if claims.Issuer != issuer {
return "", fmt.Errorf(invalidIssuer)
return "", errors.New(invalidIssuer)
}
return claims.Subject, nil
}

return "", fmt.Errorf(invalidTokenError)
return "", errors.New(invalidTokenError)
}
12 changes: 6 additions & 6 deletions internal/service/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"testing"
"time"

"github.com/golang-jwt/jwt"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"

jwtmodule "github.com/ingka-group/iam-proxy/client/jwt"
Expand Down Expand Up @@ -88,8 +88,8 @@ func TestService_ParseToken_ParseError(t *testing.T) {
func TestService_ParseToken_Expired(t *testing.T) {
srv := newTestService()

claims := &jwt.StandardClaims{
ExpiresAt: time.Now().Add(-1 * time.Second).Unix(),
claims := &jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(-1 * time.Second)),
Issuer: issuer,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
Expand All @@ -98,15 +98,15 @@ func TestService_ParseToken_Expired(t *testing.T) {

_, err = srv.ParseToken(tokenString)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "token is expired by 1s"))
assert.True(t, strings.Contains(err.Error(), "token is expired"))
assert.True(t, strings.Contains(err.Error(), parseTokenError))
}

func TestService_ParseToken_IssuerError(t *testing.T) {
srv := newTestService()

claims := &jwt.StandardClaims{
ExpiresAt: time.Now().Unix(),
claims := &jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
Issuer: "other-issuer",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
Expand Down