-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: verifiable credentials JWT format (#3614)
- Loading branch information
Showing
3 changed files
with
132 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -371,7 +371,7 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { | |
GrantAccessTokenAudience: rr.RequestedAccessTokenAudience, | ||
Session: &hydra.AcceptOAuth2ConsentRequestSession{ | ||
AccessToken: map[string]interface{}{"foo": "bar"}, | ||
IdToken: map[string]interface{}{"bar": "baz"}, | ||
IdToken: map[string]interface{}{"email": "[email protected]", "bar": "baz"}, | ||
}, | ||
}). | ||
Execute() | ||
|
@@ -1159,12 +1159,15 @@ func assertCreateVerifiableCredential(t *testing.T, reg driver.Registry, nonce s | |
}, | ||
}) | ||
require.NoError(t, err) | ||
assertVerifiableCredentialContainsPublicKey(t, reg, verifiableCredential, pubKeyJWK) | ||
require.NotNil(t, verifiableCredential) | ||
|
||
_, claims := claimsFromVCResponse(t, reg, verifiableCredential) | ||
assertClaimsContainPublicKey(t, claims, pubKeyJWK) | ||
} | ||
|
||
func assertVerifiableCredentialContainsPublicKey(t *testing.T, reg driver.Registry, vc *hydraoauth2.VerifiableCredentialResponse, pubKeyJWK *jose.JSONWebKey) { | ||
func claimsFromVCResponse(t *testing.T, reg driver.Registry, vc *hydraoauth2.VerifiableCredentialResponse) (*jwt.Token, *hydraoauth2.VerifableCredentialClaims) { | ||
ctx := context.Background() | ||
token, err := jwt.Parse(vc.Credential, func(token *jwt.Token) (interface{}, error) { | ||
token, err := jwt.ParseWithClaims(vc.Credential, new(hydraoauth2.VerifableCredentialClaims), func(token *jwt.Token) (interface{}, error) { | ||
kid, found := token.Header["kid"] | ||
if !found { | ||
return nil, errors.New("missing kid header") | ||
|
@@ -1180,10 +1183,15 @@ func assertVerifiableCredentialContainsPublicKey(t *testing.T, reg driver.Regist | |
return x.Must(reg.OpenIDJWTStrategy().GetPublicKey(ctx)).Key, nil | ||
}) | ||
require.NoError(t, err) | ||
|
||
return token, token.Claims.(*hydraoauth2.VerifableCredentialClaims) | ||
} | ||
|
||
func assertClaimsContainPublicKey(t *testing.T, claims *hydraoauth2.VerifableCredentialClaims, pubKeyJWK *jose.JSONWebKey) { | ||
pubKeyRaw, err := pubKeyJWK.MarshalJSON() | ||
require.NoError(t, err) | ||
expectedID := fmt.Sprintf("did:jwk:%s", base64.RawURLEncoding.EncodeToString(pubKeyRaw)) | ||
require.Equal(t, expectedID, token.Claims.(jwt.MapClaims)["vc"].(map[string]any)["credentialSubject"].(map[string]any)["id"]) | ||
require.Equal(t, expectedID, claims.VerifiableCredential.Subject["id"]) | ||
} | ||
|
||
func createVerifiableCredential( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright © 2023 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package oauth2 | ||
|
||
import ( | ||
"encoding/json" | ||
|
||
"github.com/golang-jwt/jwt/v5" | ||
|
||
"github.com/ory/fosite" | ||
) | ||
|
||
// Request a Verifiable Credential | ||
// | ||
// swagger:parameters createVerifiableCredential | ||
// | ||
//lint:ignore U1000 Used to generate Swagger and OpenAPI definitions | ||
type createVerifiableCredentialRequest struct { | ||
// in: body | ||
Body CreateVerifiableCredentialRequestBody | ||
} | ||
|
||
// CreateVerifiableCredentialRequestBody contains the request body to request a verifiable credential. | ||
// | ||
// swagger:parameters createVerifiableCredentialRequestBody | ||
type CreateVerifiableCredentialRequestBody struct { | ||
Format string `json:"format"` | ||
Types []string `json:"types"` | ||
Proof *VerifiableCredentialProof `json:"proof"` | ||
} | ||
|
||
// VerifiableCredentialProof contains the proof of a verifiable credential. | ||
// | ||
// swagger:parameters verifiableCredentialProof | ||
type VerifiableCredentialProof struct { | ||
ProofType string `json:"proof_type"` | ||
JWT string `json:"jwt"` | ||
} | ||
|
||
// VerifiableCredentialResponse contains the verifiable credential. | ||
// | ||
// swagger:model verifiableCredentialResponse | ||
type VerifiableCredentialResponse struct { | ||
Format string `json:"format"` | ||
Credential string `json:"credential_draft_00"` | ||
} | ||
|
||
// VerifiableCredentialPrimingResponse contains the nonce to include in the proof-of-possession JWT. | ||
// | ||
// swagger:model verifiableCredentialPrimingResponse | ||
type VerifiableCredentialPrimingResponse struct { | ||
Format string `json:"format"` | ||
Nonce string `json:"c_nonce"` | ||
NonceExpiresIn int64 `json:"c_nonce_expires_in"` | ||
|
||
fosite.RFC6749ErrorJson | ||
} | ||
|
||
type VerifableCredentialClaims struct { | ||
jwt.RegisteredClaims | ||
VerifiableCredential VerifiableCredentialClaim `json:"vc"` | ||
} | ||
type VerifiableCredentialClaim struct { | ||
Context []string `json:"@context"` | ||
Subject map[string]any `json:"credentialSubject"` | ||
Type []string `json:"type"` | ||
} | ||
|
||
func (v *VerifableCredentialClaims) GetAudience() (jwt.ClaimStrings, error) { | ||
return jwt.ClaimStrings{}, nil | ||
} | ||
|
||
func (v *VerifableCredentialClaims) ToMapClaims() (res map[string]any, err error) { | ||
res = map[string]any{} | ||
|
||
bs, err := json.Marshal(v) | ||
if err != nil { | ||
return nil, err | ||
} | ||
err = json.Unmarshal(bs, &res) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return res, nil | ||
} |