upgraded to jwt/v5

This commit is contained in:
Gani Georgiev
2025-01-05 11:05:26 +02:00
parent 41f1ff2b5f
commit b150a3a98a
11 changed files with 43 additions and 33 deletions
+8 -10
View File
@@ -6,7 +6,7 @@ import (
"errors"
"strings"
"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"
"github.com/pocketbase/pocketbase/tools/types"
"github.com/spf13/cast"
"golang.org/x/oauth2"
@@ -138,19 +138,17 @@ func (p *Apple) parseAndVerifyIdToken(idToken string) (jwt.MapClaims, error) {
// validate common claims per https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/verifying_a_user#3383769
// ---
err = claims.Valid() // exp, iat, etc.
jwtValidator := jwt.NewValidator(
jwt.WithExpirationRequired(),
jwt.WithIssuedAt(),
jwt.WithIssuer("https://appleid.apple.com"),
jwt.WithAudience(p.clientId),
)
err = jwtValidator.Validate(claims)
if err != nil {
return nil, err
}
if !claims.VerifyIssuer("https://appleid.apple.com", true) {
return nil, errors.New("iss must be https://appleid.apple.com")
}
if !claims.VerifyAudience(p.clientId, true) {
return nil, errors.New("aud must be the developer's client_id")
}
// validate id_token signature
//
// note: this step could be technically considered optional because we trust
+10 -9
View File
@@ -12,7 +12,8 @@ import (
"net/http"
"strings"
"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"
"github.com/pocketbase/pocketbase/tools/security"
"github.com/pocketbase/pocketbase/tools/types"
"github.com/spf13/cast"
"golang.org/x/oauth2"
@@ -128,24 +129,24 @@ func (p *OIDC) parseIdToken(token *oauth2.Token) (jwt.MapClaims, error) {
return nil, err
}
// validate common claims like exp, iat, etc.
err = claims.Valid()
// validate common claims
jwtValidator := jwt.NewValidator(
jwt.WithIssuedAt(),
jwt.WithAudience(p.clientId),
)
err = jwtValidator.Validate(claims)
if err != nil {
return nil, err
}
// validate aud
if !claims.VerifyAudience(p.clientId, true) {
return nil, errors.New("aud must be the developer's client_id")
}
// validate iss (if "issuers" extra config is set)
issuers := cast.ToStringSlice(p.Extra()["issuers"])
if len(issuers) > 0 {
var isIssValid bool
claimIssuer, _ := claims.GetIssuer()
for _, issuer := range issuers {
if claims.VerifyIssuer(issuer, true) {
if security.Equal(claimIssuer, issuer) {
isIssValid = true
break
}
+2 -3
View File
@@ -4,8 +4,7 @@ import (
"errors"
"time"
// @todo update to v5
"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"
)
// ParseUnverifiedJWT parses JWT and returns its claims
@@ -19,7 +18,7 @@ func ParseUnverifiedJWT(token string) (jwt.MapClaims, error) {
_, _, err := parser.ParseUnverified(token, claims)
if err == nil {
err = claims.Valid()
err = jwt.NewValidator(jwt.WithIssuedAt()).Validate(claims)
}
return claims, err
+14 -4
View File
@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"
"github.com/pocketbase/pocketbase/tools/security"
)
@@ -21,7 +21,7 @@ func TestParseUnverifiedJWT(t *testing.T) {
}
// properly formatted JWT with INVALID claims
// {"name": "test", "exp": 1516239022}
// {"name": "test", "exp":1516239022}
result2, err2 := security.ParseUnverifiedJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidGVzdCIsImV4cCI6MTUxNjIzOTAyMn0.xYHirwESfSEW3Cq2BL47CEASvD_p_ps3QCA54XtNktU")
if err2 == nil {
t.Error("Expected error got nil")
@@ -30,14 +30,24 @@ func TestParseUnverifiedJWT(t *testing.T) {
t.Errorf("Expected to have 2 claims, got %v", result2)
}
// properly formatted JWT with VALID claims
// properly formatted JWT with VALID claims (missing exp)
// {"name": "test"}
result3, err3 := security.ParseUnverifiedJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidGVzdCJ9.ml0QsTms3K9wMygTu41ZhKlTyjmW9zHQtoS8FUsCCjU")
if err3 != nil {
t.Error("Expected nil, got", err3)
}
if len(result3) != 1 || result3["name"] != "test" {
t.Errorf("Expected to have 2 claims, got %v", result3)
t.Errorf("Expected to have 1 claim, got %v", result3)
}
// properly formatted JWT with VALID claims (valid exp)
// {"name": "test", "exp": 2208985261}
result4, err4 := security.ParseUnverifiedJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidGVzdCIsImV4cCI6MjIwODk4NTI2MX0._0KQu60hYNx5wkBIpEaoX35shXRicb0X_0VdWKWb-3k")
if err4 != nil {
t.Error("Expected nil, got", err4)
}
if len(result4) != 2 || result4["name"] != "test" {
t.Errorf("Expected to have 2 claims, got %v", result4)
}
}