feat(op): add opentelemetry to token endpoint (#436)
* feat(op): add opentelemetry to token endpoint * drop go 1.18, add 1.21, do not fail fast
This commit is contained in:
parent
5ade1cd9de
commit
1683b319ae
15 changed files with 113 additions and 6 deletions
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
|
@ -15,8 +15,9 @@ jobs:
|
|||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go: ['1.18', '1.19', '1.20']
|
||||
go: ['1.19', '1.20', '1.21']
|
||||
name: Go ${{ matrix.go }} test
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
|
|
@ -115,10 +115,10 @@ Versions that also build are marked with :warning:.
|
|||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| <1.18 | :x: |
|
||||
| 1.18 | :warning: |
|
||||
| 1.19 | :white_check_mark: |
|
||||
| <1.19 | :x: |
|
||||
| 1.19 | :warning: |
|
||||
| 1.20 | :white_check_mark: |
|
||||
| 1.21 | :white_check_mark: |
|
||||
|
||||
## Why another library
|
||||
|
||||
|
|
7
go.mod
7
go.mod
|
@ -1,6 +1,6 @@
|
|||
module github.com/zitadel/oidc/v2
|
||||
|
||||
go 1.18
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.6.0
|
||||
|
@ -14,6 +14,8 @@ require (
|
|||
github.com/rs/cors v1.9.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.opentelemetry.io/otel v1.17.0
|
||||
go.opentelemetry.io/otel/trace v1.17.0
|
||||
golang.org/x/oauth2 v0.11.0
|
||||
golang.org/x/text v0.12.0
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
|
@ -21,9 +23,12 @@ require (
|
|||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.17.0 // indirect
|
||||
golang.org/x/crypto v0.12.0 // indirect
|
||||
golang.org/x/net v0.14.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
|
|
11
go.sum
11
go.sum
|
@ -1,6 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -44,6 +49,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM=
|
||||
go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0=
|
||||
go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc=
|
||||
go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o=
|
||||
go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ=
|
||||
go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
|
|
|
@ -464,6 +464,10 @@ func AuthResponseCode(w http.ResponseWriter, r *http.Request, authReq AuthReques
|
|||
|
||||
// AuthResponseToken creates the successful token(s) authentication response
|
||||
func AuthResponseToken(w http.ResponseWriter, r *http.Request, authReq AuthRequest, authorizer Authorizer, client Client) {
|
||||
ctx, span := tracer.Start(r.Context(), "AuthResponseToken")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
createAccessToken := authReq.GetResponseType() != oidc.ResponseTypeIDTokenOnly
|
||||
resp, err := CreateTokenResponse(r.Context(), authReq, client, authorizer, createAccessToken, "", "")
|
||||
if err != nil {
|
||||
|
|
|
@ -196,6 +196,10 @@ func (r *deviceAccessTokenRequest) GetScopes() []string {
|
|||
}
|
||||
|
||||
func DeviceAccessToken(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
ctx, span := tracer.Start(r.Context(), "DeviceAccessToken")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
if err := deviceAccessToken(w, r, exchanger); err != nil {
|
||||
RequestError(w, r, err)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/schema"
|
||||
"github.com/rs/cors"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"golang.org/x/text/language"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
|
||||
|
@ -67,6 +69,12 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
var tracer trace.Tracer
|
||||
|
||||
func init() {
|
||||
tracer = otel.Tracer("github.com/zitadel/oidc/pkg/op")
|
||||
}
|
||||
|
||||
type OpenIDProvider interface {
|
||||
Configuration
|
||||
Storage() Storage
|
||||
|
|
|
@ -28,6 +28,9 @@ type AccessTokenClient interface {
|
|||
}
|
||||
|
||||
func CreateTokenResponse(ctx context.Context, request IDTokenRequest, client Client, creator TokenCreator, createAccessToken bool, code, refreshToken string) (*oidc.AccessTokenResponse, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateTokenResponse")
|
||||
defer span.End()
|
||||
|
||||
var accessToken, newRefreshToken string
|
||||
var validity time.Duration
|
||||
if createAccessToken {
|
||||
|
@ -84,6 +87,9 @@ func needsRefreshToken(tokenRequest TokenRequest, client AccessTokenClient) bool
|
|||
}
|
||||
|
||||
func CreateAccessToken(ctx context.Context, tokenRequest TokenRequest, accessTokenType AccessTokenType, creator TokenCreator, client AccessTokenClient, refreshToken string) (accessToken, newRefreshToken string, validity time.Duration, err error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateAccessToken")
|
||||
defer span.End()
|
||||
|
||||
id, newRefreshToken, exp, err := createTokens(ctx, tokenRequest, creator.Storage(), refreshToken, client)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
|
@ -97,7 +103,9 @@ func CreateAccessToken(ctx context.Context, tokenRequest TokenRequest, accessTok
|
|||
accessToken, err = CreateJWT(ctx, IssuerFromContext(ctx), tokenRequest, exp, id, client, creator.Storage())
|
||||
return
|
||||
}
|
||||
_, span = tracer.Start(ctx, "CreateBearerToken")
|
||||
accessToken, err = CreateBearerToken(id, tokenRequest.GetSubject(), creator.Crypto())
|
||||
span.End()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -106,6 +114,9 @@ func CreateBearerToken(tokenID, subject string, crypto Crypto) (string, error) {
|
|||
}
|
||||
|
||||
func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, exp time.Time, id string, client AccessTokenClient, storage Storage) (string, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateJWT")
|
||||
defer span.End()
|
||||
|
||||
claims := oidc.NewAccessTokenClaims(issuer, tokenRequest.GetSubject(), tokenRequest.GetAudience(), exp, id, client.GetID(), client.ClockSkew())
|
||||
if client != nil {
|
||||
restrictedScopes := client.RestrictAdditionalAccessTokenScopes()(tokenRequest.GetScopes())
|
||||
|
@ -152,6 +163,9 @@ type IDTokenRequest interface {
|
|||
}
|
||||
|
||||
func CreateIDToken(ctx context.Context, issuer string, request IDTokenRequest, validity time.Duration, accessToken, code string, storage Storage, client Client) (string, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateIDToken")
|
||||
defer span.End()
|
||||
|
||||
exp := time.Now().UTC().Add(client.ClockSkew()).Add(validity)
|
||||
var acr, nonce string
|
||||
if authRequest, ok := request.(AuthRequest); ok {
|
||||
|
|
|
@ -12,6 +12,10 @@ import (
|
|||
// ClientCredentialsExchange handles the OAuth 2.0 client_credentials grant, including
|
||||
// parsing, validating, authorizing the client and finally returning a token
|
||||
func ClientCredentialsExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
ctx, span := tracer.Start(r.Context(), "ClientCredentialsExchange")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
request, err := ParseClientCredentialsRequest(r, exchanger.Decoder())
|
||||
if err != nil {
|
||||
RequestError(w, r, err)
|
||||
|
@ -66,6 +70,9 @@ func ParseClientCredentialsRequest(r *http.Request, decoder httphelper.Decoder)
|
|||
// ValidateClientCredentialsRequest validates the client_credentials request parameters including authorization check of the client
|
||||
// and returns a TokenRequest and Client implementation to be used in the client_credentials response, resp. creation of the corresponding access_token.
|
||||
func ValidateClientCredentialsRequest(ctx context.Context, request *oidc.ClientCredentialsRequest, exchanger Exchanger) (TokenRequest, Client, error) {
|
||||
ctx, span := tracer.Start(ctx, "ValidateClientCredentialsRequest")
|
||||
defer span.End()
|
||||
|
||||
storage, ok := exchanger.Storage().(ClientCredentialsStorage)
|
||||
if !ok {
|
||||
return nil, nil, oidc.ErrUnsupportedGrantType().WithDescription("client_credentials grant not supported")
|
||||
|
@ -85,6 +92,9 @@ func ValidateClientCredentialsRequest(ctx context.Context, request *oidc.ClientC
|
|||
}
|
||||
|
||||
func AuthorizeClientCredentialsClient(ctx context.Context, request *oidc.ClientCredentialsRequest, storage ClientCredentialsStorage) (Client, error) {
|
||||
ctx, span := tracer.Start(ctx, "AuthorizeClientCredentialsClient")
|
||||
defer span.End()
|
||||
|
||||
client, err := storage.ClientCredentials(ctx, request.ClientID, request.ClientSecret)
|
||||
if err != nil {
|
||||
return nil, oidc.ErrInvalidClient().WithParent(err)
|
||||
|
@ -98,6 +108,9 @@ func AuthorizeClientCredentialsClient(ctx context.Context, request *oidc.ClientC
|
|||
}
|
||||
|
||||
func CreateClientCredentialsTokenResponse(ctx context.Context, tokenRequest TokenRequest, creator TokenCreator, client Client) (*oidc.AccessTokenResponse, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateClientCredentialsTokenResponse")
|
||||
defer span.End()
|
||||
|
||||
accessToken, _, validity, err := CreateAccessToken(ctx, tokenRequest, client.AccessTokenType(), creator, client, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -11,6 +11,10 @@ import (
|
|||
// CodeExchange handles the OAuth 2.0 authorization_code grant, including
|
||||
// parsing, validating, authorizing the client and finally exchanging the code for tokens
|
||||
func CodeExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
ctx, span := tracer.Start(r.Context(), "CodeExchange")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
tokenReq, err := ParseAccessTokenRequest(r, exchanger.Decoder())
|
||||
if err != nil {
|
||||
RequestError(w, r, err)
|
||||
|
@ -45,6 +49,9 @@ func ParseAccessTokenRequest(r *http.Request, decoder httphelper.Decoder) (*oidc
|
|||
// ValidateAccessTokenRequest validates the token request parameters including authorization check of the client
|
||||
// and returns the previous created auth request corresponding to the auth code
|
||||
func ValidateAccessTokenRequest(ctx context.Context, tokenReq *oidc.AccessTokenRequest, exchanger Exchanger) (AuthRequest, Client, error) {
|
||||
ctx, span := tracer.Start(ctx, "ValidateAccessTokenRequest")
|
||||
defer span.End()
|
||||
|
||||
authReq, client, err := AuthorizeCodeClient(ctx, tokenReq, exchanger)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -64,6 +71,9 @@ func ValidateAccessTokenRequest(ctx context.Context, tokenReq *oidc.AccessTokenR
|
|||
// AuthorizeCodeClient checks the authorization of the client and that the used method was the one previously registered.
|
||||
// It than returns the auth request corresponding to the auth code
|
||||
func AuthorizeCodeClient(ctx context.Context, tokenReq *oidc.AccessTokenRequest, exchanger Exchanger) (request AuthRequest, client Client, err error) {
|
||||
ctx, span := tracer.Start(ctx, "AuthorizeCodeClient")
|
||||
defer span.End()
|
||||
|
||||
if tokenReq.ClientAssertionType == oidc.ClientAssertionTypeJWTAssertion {
|
||||
jwtExchanger, ok := exchanger.(JWTAuthorizationGrantExchanger)
|
||||
if !ok || !exchanger.AuthMethodPrivateKeyJWTSupported() {
|
||||
|
@ -104,6 +114,9 @@ func AuthorizeCodeClient(ctx context.Context, tokenReq *oidc.AccessTokenRequest,
|
|||
|
||||
// AuthRequestByCode returns the AuthRequest previously created from Storage corresponding to the auth code or an error
|
||||
func AuthRequestByCode(ctx context.Context, storage Storage, code string) (AuthRequest, error) {
|
||||
ctx, span := tracer.Start(ctx, "AuthRequestByCode")
|
||||
defer span.End()
|
||||
|
||||
authReq, err := storage.AuthRequestByCode(ctx, code)
|
||||
if err != nil {
|
||||
return nil, oidc.ErrInvalidGrant().WithDescription("invalid code").WithParent(err)
|
||||
|
|
|
@ -134,6 +134,10 @@ func (r *tokenExchangeRequest) SetSubject(subject string) {
|
|||
|
||||
// TokenExchange handles the OAuth 2.0 token exchange grant ("urn:ietf:params:oauth:grant-type:token-exchange")
|
||||
func TokenExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
ctx, span := tracer.Start(r.Context(), "TokenExchange")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
tokenExchangeReq, clientID, clientSecret, err := ParseTokenExchangeRequest(r, exchanger.Decoder())
|
||||
if err != nil {
|
||||
RequestError(w, r, err)
|
||||
|
|
|
@ -16,6 +16,10 @@ type JWTAuthorizationGrantExchanger interface {
|
|||
|
||||
// JWTProfile handles the OAuth 2.0 JWT Profile Authorization Grant https://tools.ietf.org/html/rfc7523#section-2.1
|
||||
func JWTProfile(w http.ResponseWriter, r *http.Request, exchanger JWTAuthorizationGrantExchanger) {
|
||||
ctx, span := tracer.Start(r.Context(), "JWTProfile")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
profileRequest, err := ParseJWTProfileGrantRequest(r, exchanger.Decoder())
|
||||
if err != nil {
|
||||
RequestError(w, r, err)
|
||||
|
@ -56,6 +60,9 @@ func ParseJWTProfileGrantRequest(r *http.Request, decoder httphelper.Decoder) (*
|
|||
// CreateJWTTokenResponse creates an access_token response for a JWT Profile Grant request
|
||||
// by default the access_token is an opaque string, but can be specified by implementing the JWTProfileTokenStorage interface
|
||||
func CreateJWTTokenResponse(ctx context.Context, tokenRequest TokenRequest, creator TokenCreator) (*oidc.AccessTokenResponse, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateJWTTokenResponse")
|
||||
defer span.End()
|
||||
|
||||
// return an opaque token as default to not break current implementations
|
||||
tokenType := AccessTokenTypeBearer
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@ type RefreshTokenRequest interface {
|
|||
// RefreshTokenExchange handles the OAuth 2.0 refresh_token grant, including
|
||||
// parsing, validating, authorizing the client and finally exchanging the refresh_token for new tokens
|
||||
func RefreshTokenExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
ctx, span := tracer.Start(r.Context(), "RefreshTokenExchange")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
tokenReq, err := ParseRefreshTokenRequest(r, exchanger.Decoder())
|
||||
if err != nil {
|
||||
RequestError(w, r, err)
|
||||
|
@ -54,6 +58,9 @@ func ParseRefreshTokenRequest(r *http.Request, decoder httphelper.Decoder) (*oid
|
|||
// ValidateRefreshTokenRequest validates the refresh_token request parameters including authorization check of the client
|
||||
// and returns the data representing the original auth request corresponding to the refresh_token
|
||||
func ValidateRefreshTokenRequest(ctx context.Context, tokenReq *oidc.RefreshTokenRequest, exchanger Exchanger) (RefreshTokenRequest, Client, error) {
|
||||
ctx, span := tracer.Start(ctx, "ValidateRefreshTokenRequest")
|
||||
defer span.End()
|
||||
|
||||
if tokenReq.RefreshToken == "" {
|
||||
return nil, nil, oidc.ErrInvalidRequest().WithDescription("refresh_token missing")
|
||||
}
|
||||
|
@ -89,6 +96,9 @@ func ValidateRefreshTokenScopes(requestedScopes []string, authRequest RefreshTok
|
|||
// AuthorizeRefreshClient checks the authorization of the client and that the used method was the one previously registered.
|
||||
// It than returns the data representing the original auth request corresponding to the refresh_token
|
||||
func AuthorizeRefreshClient(ctx context.Context, tokenReq *oidc.RefreshTokenRequest, exchanger Exchanger) (request RefreshTokenRequest, client Client, err error) {
|
||||
ctx, span := tracer.Start(ctx, "AuthorizeRefreshClient")
|
||||
defer span.End()
|
||||
|
||||
if tokenReq.ClientAssertionType == oidc.ClientAssertionTypeJWTAssertion {
|
||||
jwtExchanger, ok := exchanger.(JWTAuthorizationGrantExchanger)
|
||||
if !ok || !exchanger.AuthMethodPrivateKeyJWTSupported() {
|
||||
|
|
|
@ -26,7 +26,10 @@ type Exchanger interface {
|
|||
|
||||
func tokenHandler(exchanger Exchanger) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
Exchange(w, r, exchanger)
|
||||
ctx, span := tracer.Start(r.Context(), "tokenHandler")
|
||||
defer span.End()
|
||||
|
||||
Exchange(w, r.WithContext(ctx), exchanger)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +82,10 @@ type AuthenticatedTokenRequest interface {
|
|||
// ParseAuthenticatedTokenRequest parses the client_id and client_secret from the HTTP request from either
|
||||
// HTTP Basic Auth header or form body and sets them into the provided authenticatedTokenRequest interface
|
||||
func ParseAuthenticatedTokenRequest(r *http.Request, decoder httphelper.Decoder, request AuthenticatedTokenRequest) error {
|
||||
ctx, span := tracer.Start(r.Context(), "ParseAuthenticatedTokenRequest")
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return oidc.ErrInvalidRequest().WithDescription("error parsing form").WithParent(err)
|
||||
|
@ -128,6 +135,9 @@ func AuthorizeCodeChallenge(tokenReq *oidc.AccessTokenRequest, challenge *oidc.C
|
|||
// AuthorizePrivateJWTKey authorizes a client by validating the client_assertion's signature with a previously
|
||||
// registered public key (JWT Profile)
|
||||
func AuthorizePrivateJWTKey(ctx context.Context, clientAssertion string, exchanger JWTAuthorizationGrantExchanger) (Client, error) {
|
||||
ctx, span := tracer.Start(ctx, "AuthorizePrivateJWTKey")
|
||||
defer span.End()
|
||||
|
||||
jwtReq, err := VerifyJWTAssertion(ctx, clientAssertion, exchanger.JWTProfileVerifier(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -74,6 +74,9 @@ func (v *jwtProfileVerifier) CheckSubject(request *oidc.JWTTokenRequest) error {
|
|||
//
|
||||
// checks audience, exp, iat, signature and that issuer and sub are the same
|
||||
func VerifyJWTAssertion(ctx context.Context, assertion string, v JWTProfileVerifier) (*oidc.JWTTokenRequest, error) {
|
||||
ctx, span := tracer.Start(ctx, "VerifyJWTAssertion")
|
||||
defer span.End()
|
||||
|
||||
request := new(oidc.JWTTokenRequest)
|
||||
payload, err := oidc.ParseToken(assertion, request)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue