1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-06-15 00:15:00 +02:00
Files
oauth2-proxy/pkg/providers/oidc/verifier.go

110 lines
3.5 KiB
Go
Raw Permalink Normal View History

improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
package oidc
import (
"context"
"fmt"
"reflect"
"github.com/coreos/go-oidc/v3/oidc"
)
// idTokenVerifier allows an ID Token to be verified against the issue and provided keys.
type IDTokenVerifier interface {
Verify(context.Context, string) (*oidc.IDToken, error)
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
}
// idTokenVerifier Used to verify an ID Token and extends oidc.idTokenVerifier from the underlying oidc library
type idTokenVerifier struct {
verifier *oidc.IDTokenVerifier
verificationOptions IDTokenVerificationOptions
allowedAudiences map[string]struct{}
}
// IDTokenVerificationOptions options for the oidc.idTokenVerifier that are required to verify an ID Token
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
type IDTokenVerificationOptions struct {
AudienceClaims []string
ClientID string
ExtraAudiences []string
}
// NewVerifier constructs a new idTokenVerifier
func NewVerifier(iv *oidc.IDTokenVerifier, vo IDTokenVerificationOptions) IDTokenVerifier {
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
allowedAudiences := make(map[string]struct{})
allowedAudiences[vo.ClientID] = struct{}{}
for _, extraAudience := range vo.ExtraAudiences {
allowedAudiences[extraAudience] = struct{}{}
}
return &idTokenVerifier{
verifier: iv,
verificationOptions: vo,
allowedAudiences: allowedAudiences,
}
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
}
// Verify verifies incoming ID Token
func (v *idTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*oidc.IDToken, error) {
token, err := v.verifier.Verify(ctx, rawIDToken)
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
if err != nil {
return nil, fmt.Errorf("failed to verify token: %v", err)
}
claims := map[string]interface{}{}
if err := token.Claims(&claims); err != nil {
return nil, fmt.Errorf("failed to parse default id_token claims: %v", err)
}
if isValidAudience, err := v.verifyAudience(token, claims); !isValidAudience {
return nil, err
}
return token, err
}
func (v *idTokenVerifier) verifyAudience(token *oidc.IDToken, claims map[string]interface{}) (bool, error) {
for _, audienceClaim := range v.verificationOptions.AudienceClaims {
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
if audienceClaimValue, audienceClaimExists := claims[audienceClaim]; audienceClaimExists {
// audience claim value can be either interface{} or []interface{},
// as per spec `aud` can be either a string or a list of strings
switch audienceClaimValueType := audienceClaimValue.(type) {
case []interface{}:
token.Audience = v.interfaceSliceToString(audienceClaimValue)
case interface{}:
token.Audience = []string{audienceClaimValue.(string)}
default:
return false, fmt.Errorf("audience claim %s holds unsupported type %T",
audienceClaim, audienceClaimValueType)
}
return v.isValidAudience(audienceClaim, token.Audience, v.allowedAudiences)
}
}
return false, fmt.Errorf("audience claims %v do not exist in claims: %v",
v.verificationOptions.AudienceClaims, claims)
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
}
func (v *idTokenVerifier) isValidAudience(claim string, audience []string, allowedAudiences map[string]struct{}) (bool, error) {
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
for _, aud := range audience {
if _, allowedAudienceExists := allowedAudiences[aud]; allowedAudienceExists {
return true, nil
}
}
return false, fmt.Errorf(
"audience from claim %s with value %s does not match with any of allowed audiences %v",
claim, audience, allowedAudiences)
}
func (v *idTokenVerifier) interfaceSliceToString(slice interface{}) []string {
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 17:12:22 +01:00
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic(fmt.Sprintf("given a non-slice type %s", s.Kind()))
}
var strings []string
for i := 0; i < s.Len(); i++ {
strings = append(strings, s.Index(i).Interface().(string))
}
return strings
}