Merge branch 'main' into extend-tracing
This commit is contained in:
commit
0ffd13c780
6 changed files with 71 additions and 23 deletions
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ go 1.21
|
|||
require (
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
github.com/go-jose/go-jose/v3 v3.0.2
|
||||
github.com/go-jose/go-jose/v3 v3.0.3
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-github/v31 v31.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -5,8 +5,8 @@ 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-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-jose/go-jose/v3 v3.0.2 h1:2Edjn8Nrb44UvTdp84KU0bBPs1cO7noRCybtS3eJEUQ=
|
||||
github.com/go-jose/go-jose/v3 v3.0.2/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-jose/go-jose/v3"
|
||||
"github.com/zitadel/oidc/v3/pkg/client"
|
||||
httphelper "github.com/zitadel/oidc/v3/pkg/http"
|
||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||
|
@ -33,6 +35,17 @@ func NewTokenExchangerClientCredentials(ctx context.Context, issuer, clientID, c
|
|||
return newOAuthTokenExchange(ctx, issuer, authorizer, options...)
|
||||
}
|
||||
|
||||
func NewTokenExchangerJWTProfile(ctx context.Context, issuer, clientID string, signer jose.Signer, options ...func(source *OAuthTokenExchange)) (TokenExchanger, error) {
|
||||
authorizer := func() (any, error) {
|
||||
assertion, err := client.SignedJWTProfileAssertion(clientID, []string{issuer}, time.Hour, signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.ClientAssertionFormAuthorization(assertion), nil
|
||||
}
|
||||
return newOAuthTokenExchange(ctx, issuer, authorizer, options...)
|
||||
}
|
||||
|
||||
func newOAuthTokenExchange(ctx context.Context, issuer string, authorizer func() (any, error), options ...func(source *OAuthTokenExchange)) (*OAuthTokenExchange, error) {
|
||||
te := &OAuthTokenExchange{
|
||||
httpClient: httphelper.DefaultHTTPClient,
|
||||
|
|
|
@ -27,6 +27,11 @@ const (
|
|||
SlowDown errorType = "slow_down"
|
||||
AccessDenied errorType = "access_denied"
|
||||
ExpiredToken errorType = "expired_token"
|
||||
|
||||
// InvalidTarget error is returned by Token Exchange if
|
||||
// the requested target or audience is invalid.
|
||||
// [RFC 8693, Section 2.2.2: Error Response](https://www.rfc-editor.org/rfc/rfc8693#section-2.2.2)
|
||||
InvalidTarget errorType = "invalid_target"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -112,6 +117,14 @@ var (
|
|||
Description: "The \"device_code\" has expired.",
|
||||
}
|
||||
}
|
||||
|
||||
// Token exchange error
|
||||
ErrInvalidTarget = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InvalidTarget,
|
||||
Description: "The requested audience or target is invalid.",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
|
|
|
@ -34,19 +34,20 @@ type Tokens[C IDClaims] struct {
|
|||
// TokenClaims implements the Claims interface,
|
||||
// and can be used to extend larger claim types by embedding.
|
||||
type TokenClaims struct {
|
||||
Issuer string `json:"iss,omitempty"`
|
||||
Subject string `json:"sub,omitempty"`
|
||||
Audience Audience `json:"aud,omitempty"`
|
||||
Expiration Time `json:"exp,omitempty"`
|
||||
IssuedAt Time `json:"iat,omitempty"`
|
||||
AuthTime Time `json:"auth_time,omitempty"`
|
||||
NotBefore Time `json:"nbf,omitempty"`
|
||||
Nonce string `json:"nonce,omitempty"`
|
||||
AuthenticationContextClassReference string `json:"acr,omitempty"`
|
||||
AuthenticationMethodsReferences []string `json:"amr,omitempty"`
|
||||
AuthorizedParty string `json:"azp,omitempty"`
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
JWTID string `json:"jti,omitempty"`
|
||||
Issuer string `json:"iss,omitempty"`
|
||||
Subject string `json:"sub,omitempty"`
|
||||
Audience Audience `json:"aud,omitempty"`
|
||||
Expiration Time `json:"exp,omitempty"`
|
||||
IssuedAt Time `json:"iat,omitempty"`
|
||||
AuthTime Time `json:"auth_time,omitempty"`
|
||||
NotBefore Time `json:"nbf,omitempty"`
|
||||
Nonce string `json:"nonce,omitempty"`
|
||||
AuthenticationContextClassReference string `json:"acr,omitempty"`
|
||||
AuthenticationMethodsReferences []string `json:"amr,omitempty"`
|
||||
AuthorizedParty string `json:"azp,omitempty"`
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
JWTID string `json:"jti,omitempty"`
|
||||
Actor *ActorClaims `json:"act,omitempty"`
|
||||
|
||||
// Additional information set by this framework
|
||||
SignatureAlg jose.SignatureAlgorithm `json:"-"`
|
||||
|
@ -204,6 +205,28 @@ func (i *IDTokenClaims) UnmarshalJSON(data []byte) error {
|
|||
return unmarshalJSONMulti(data, (*itcAlias)(i), &i.Claims)
|
||||
}
|
||||
|
||||
// ActorClaims provides the `act` claims used for impersonation or delegation Token Exchange.
|
||||
//
|
||||
// An actor can be nested in case an obtained token is used as actor token to obtain impersonation or delegation.
|
||||
// This allows creating a chain of actors.
|
||||
// See [RFC 8693, section 4.1](https://www.rfc-editor.org/rfc/rfc8693#name-act-actor-claim).
|
||||
type ActorClaims struct {
|
||||
Actor *ActorClaims `json:"act,omitempty"`
|
||||
Issuer string `json:"iss,omitempty"`
|
||||
Subject string `json:"sub,omitempty"`
|
||||
Claims map[string]any `json:"-"`
|
||||
}
|
||||
|
||||
type acAlias ActorClaims
|
||||
|
||||
func (c *ActorClaims) MarshalJSON() ([]byte, error) {
|
||||
return mergeAndMarshalClaims((*acAlias)(c), c.Claims)
|
||||
}
|
||||
|
||||
func (c *ActorClaims) UnmarshalJSON(data []byte) error {
|
||||
return unmarshalJSONMulti(data, (*acAlias)(c), &c.Claims)
|
||||
}
|
||||
|
||||
type AccessTokenResponse struct {
|
||||
AccessToken string `json:"access_token,omitempty" schema:"access_token,omitempty"`
|
||||
TokenType string `json:"token_type,omitempty" schema:"token_type,omitempty"`
|
||||
|
@ -352,4 +375,8 @@ type TokenExchangeResponse struct {
|
|||
ExpiresIn uint64 `json:"expires_in,omitempty"`
|
||||
Scopes SpaceDelimitedArray `json:"scope,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
|
||||
// IDToken field allows returning an additional ID token
|
||||
// if the requested_token_type was Access Token and scope contained openid.
|
||||
IDToken string `json:"id_token,omitempty"`
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package oidc
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
jose "github.com/go-jose/go-jose/v3"
|
||||
|
@ -57,13 +58,7 @@ var AllTokenTypes = []TokenType{
|
|||
type TokenType string
|
||||
|
||||
func (t TokenType) IsSupported() bool {
|
||||
for _, tt := range AllTokenTypes {
|
||||
if t == tt {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return slices.Contains(AllTokenTypes, t)
|
||||
}
|
||||
|
||||
type TokenRequest interface {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue