build(deps): bump the go-deps group with 10 updates
Bumps the go-deps group with 10 updates: | Package | From | To | | --- | --- | --- | | [cloud.google.com/go/compute](https://github.com/googleapis/google-cloud-go) | `1.23.3` | `1.23.4` | | [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) | `1.36.0` | `1.37.0` | | [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) | `1.4.0` | `1.5.1` | | [github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5](https://github.com/Azure/azure-sdk-for-go) | `5.3.0` | `5.5.0` | | [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) | `1.50.0` | `1.50.8` | | [github.com/google/uuid](https://github.com/google/uuid) | `1.5.0` | `1.6.0` | | [github.com/jackc/pgtype](https://github.com/jackc/pgtype) | `1.14.0` | `1.14.1` | | [github.com/openshift-online/ocm-sdk-go](https://github.com/openshift-online/ocm-sdk-go) | `0.1.390` | `0.1.398` | | [github.com/osbuild/images](https://github.com/osbuild/images) | `0.33.0` | `0.34.0` | | [google.golang.org/api](https://github.com/googleapis/google-api-go-client) | `0.160.0` | `0.161.0` | Updates `cloud.google.com/go/compute` from 1.23.3 to 1.23.4 - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/compute/v1.23.3...compute/v1.23.4) Updates `cloud.google.com/go/storage` from 1.36.0 to 1.37.0 - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.36.0...spanner/v1.37.0) Updates `github.com/Azure/azure-sdk-for-go/sdk/azidentity` from 1.4.0 to 1.5.1 - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.4.0...sdk/internal/v1.5.1) Updates `github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5` from 5.3.0 to 5.5.0 - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/resourcemanager/compute/armcompute/v5.3.0...sdk/resourcemanager/compute/armcompute/v5.5.0) Updates `github.com/aws/aws-sdk-go` from 1.50.0 to 1.50.8 - [Release notes](https://github.com/aws/aws-sdk-go/releases) - [Commits](https://github.com/aws/aws-sdk-go/compare/v1.50.0...v1.50.8) Updates `github.com/google/uuid` from 1.5.0 to 1.6.0 - [Release notes](https://github.com/google/uuid/releases) - [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) Updates `github.com/jackc/pgtype` from 1.14.0 to 1.14.1 - [Changelog](https://github.com/jackc/pgtype/blob/master/CHANGELOG.md) - [Commits](https://github.com/jackc/pgtype/compare/v1.14.0...v1.14.1) Updates `github.com/openshift-online/ocm-sdk-go` from 0.1.390 to 0.1.398 - [Release notes](https://github.com/openshift-online/ocm-sdk-go/releases) - [Changelog](https://github.com/openshift-online/ocm-sdk-go/blob/main/CHANGES.md) - [Commits](https://github.com/openshift-online/ocm-sdk-go/compare/v0.1.390...v0.1.398) Updates `github.com/osbuild/images` from 0.33.0 to 0.34.0 - [Release notes](https://github.com/osbuild/images/releases) - [Commits](https://github.com/osbuild/images/compare/v0.33.0...v0.34.0) Updates `google.golang.org/api` from 0.160.0 to 0.161.0 - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.160.0...v0.161.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/compute dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-deps - dependency-name: cloud.google.com/go/storage dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-deps - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-deps - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-deps - dependency-name: github.com/aws/aws-sdk-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-deps - dependency-name: github.com/google/uuid dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-deps - dependency-name: github.com/jackc/pgtype dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-deps - dependency-name: github.com/openshift-online/ocm-sdk-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-deps - dependency-name: github.com/osbuild/images dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-deps - dependency-name: google.golang.org/api dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-deps ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
parent
db0e6c9643
commit
b461b1faf3
306 changed files with 80393 additions and 56486 deletions
|
|
@ -59,6 +59,8 @@ added, it doesn't exist in real life. As such I've put a PEM decoder into here.
|
|||
// For details see https://aka.ms/msal-net-authenticationresult
|
||||
type AuthResult = base.AuthResult
|
||||
|
||||
type AuthenticationScheme = authority.AuthenticationScheme
|
||||
|
||||
type Account = shared.Account
|
||||
|
||||
// CertFromPEM converts a PEM file (.pem or .key) for use with [NewCredFromCert]. The file
|
||||
|
|
@ -454,6 +456,33 @@ func WithClaims(claims string) interface {
|
|||
}
|
||||
}
|
||||
|
||||
// WithAuthenticationScheme is an extensibility mechanism designed to be used only by Azure Arc for proof of possession access tokens.
|
||||
func WithAuthenticationScheme(authnScheme AuthenticationScheme) interface {
|
||||
AcquireSilentOption
|
||||
AcquireByCredentialOption
|
||||
options.CallOption
|
||||
} {
|
||||
return struct {
|
||||
AcquireSilentOption
|
||||
AcquireByCredentialOption
|
||||
options.CallOption
|
||||
}{
|
||||
CallOption: options.NewCallOption(
|
||||
func(a any) error {
|
||||
switch t := a.(type) {
|
||||
case *acquireTokenSilentOptions:
|
||||
t.authnScheme = authnScheme
|
||||
case *acquireTokenByCredentialOptions:
|
||||
t.authnScheme = authnScheme
|
||||
default:
|
||||
return fmt.Errorf("unexpected options type %T", a)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// WithTenantID specifies a tenant for a single authentication. It may be different than the tenant set in [New].
|
||||
// This option is valid for any token acquisition method.
|
||||
func WithTenantID(tenantID string) interface {
|
||||
|
|
@ -499,6 +528,7 @@ func WithTenantID(tenantID string) interface {
|
|||
type acquireTokenSilentOptions struct {
|
||||
account Account
|
||||
claims, tenantID string
|
||||
authnScheme AuthenticationScheme
|
||||
}
|
||||
|
||||
// AcquireSilentOption is implemented by options for AcquireTokenSilent
|
||||
|
|
@ -549,6 +579,7 @@ func (cca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts
|
|||
Credential: cca.cred,
|
||||
IsAppCache: o.account.IsZero(),
|
||||
TenantID: o.tenantID,
|
||||
AuthnScheme: o.authnScheme,
|
||||
}
|
||||
|
||||
return cca.base.AcquireTokenSilent(ctx, silentParameters)
|
||||
|
|
@ -614,6 +645,7 @@ func (cca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redir
|
|||
// acquireTokenByCredentialOptions contains optional configuration for AcquireTokenByCredential
|
||||
type acquireTokenByCredentialOptions struct {
|
||||
claims, tenantID string
|
||||
authnScheme AuthenticationScheme
|
||||
}
|
||||
|
||||
// AcquireByCredentialOption is implemented by options for AcquireTokenByCredential
|
||||
|
|
@ -637,7 +669,9 @@ func (cca Client) AcquireTokenByCredential(ctx context.Context, scopes []string,
|
|||
authParams.Scopes = scopes
|
||||
authParams.AuthorizationType = authority.ATClientCredentials
|
||||
authParams.Claims = o.claims
|
||||
|
||||
if o.authnScheme != nil {
|
||||
authParams.AuthnScheme = o.authnScheme
|
||||
}
|
||||
token, err := cca.base.Token.Credential(ctx, authParams, cca.cred)
|
||||
if err != nil {
|
||||
return AuthResult{}, err
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ type AcquireTokenSilentParameters struct {
|
|||
UserAssertion string
|
||||
AuthorizationType authority.AuthorizeType
|
||||
Claims string
|
||||
AuthnScheme authority.AuthenticationScheme
|
||||
}
|
||||
|
||||
// AcquireTokenAuthCodeParameters contains the parameters required to acquire an access token using the auth code flow.
|
||||
|
|
@ -289,6 +290,9 @@ func (b Client) AcquireTokenSilent(ctx context.Context, silent AcquireTokenSilen
|
|||
authParams.AuthorizationType = silent.AuthorizationType
|
||||
authParams.Claims = silent.Claims
|
||||
authParams.UserAssertion = silent.UserAssertion
|
||||
if silent.AuthnScheme != nil {
|
||||
authParams.AuthnScheme = silent.AuthnScheme
|
||||
}
|
||||
|
||||
m := b.pmanager
|
||||
if authParams.AuthorizationType != authority.ATOnBehalfOf {
|
||||
|
|
@ -313,6 +317,7 @@ func (b Client) AcquireTokenSilent(ctx context.Context, silent AcquireTokenSilen
|
|||
if silent.Claims == "" {
|
||||
ar, err = AuthResultFromStorage(storageTokenResponse)
|
||||
if err == nil {
|
||||
ar.AccessToken, err = authParams.AuthnScheme.FormatAccessToken(ar.AccessToken)
|
||||
return ar, err
|
||||
}
|
||||
}
|
||||
|
|
@ -417,6 +422,11 @@ func (b Client) AuthResultFromToken(ctx context.Context, authParams authority.Au
|
|||
if err == nil && b.cacheAccessor != nil {
|
||||
err = b.cacheAccessor.Export(ctx, b.manager, cache.ExportHints{PartitionKey: key})
|
||||
}
|
||||
if err != nil {
|
||||
return AuthResult{}, err
|
||||
}
|
||||
|
||||
ar.AccessToken, err = authParams.AuthnScheme.FormatAccessToken(ar.AccessToken)
|
||||
return ar, err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
internalTime "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/json/types/time"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared"
|
||||
)
|
||||
|
||||
|
|
@ -75,12 +76,14 @@ type AccessToken struct {
|
|||
ExtendedExpiresOn internalTime.Unix `json:"extended_expires_on,omitempty"`
|
||||
CachedAt internalTime.Unix `json:"cached_at,omitempty"`
|
||||
UserAssertionHash string `json:"user_assertion_hash,omitempty"`
|
||||
TokenType string `json:"token_type,omitempty"`
|
||||
AuthnSchemeKeyID string `json:"keyid,omitempty"`
|
||||
|
||||
AdditionalFields map[string]interface{}
|
||||
}
|
||||
|
||||
// NewAccessToken is the constructor for AccessToken.
|
||||
func NewAccessToken(homeID, env, realm, clientID string, cachedAt, expiresOn, extendedExpiresOn time.Time, scopes, token string) AccessToken {
|
||||
func NewAccessToken(homeID, env, realm, clientID string, cachedAt, expiresOn, extendedExpiresOn time.Time, scopes, token, tokenType, authnSchemeKeyID string) AccessToken {
|
||||
return AccessToken{
|
||||
HomeAccountID: homeID,
|
||||
Environment: env,
|
||||
|
|
@ -92,6 +95,8 @@ func NewAccessToken(homeID, env, realm, clientID string, cachedAt, expiresOn, ex
|
|||
CachedAt: internalTime.Unix{T: cachedAt.UTC()},
|
||||
ExpiresOn: internalTime.Unix{T: expiresOn.UTC()},
|
||||
ExtendedExpiresOn: internalTime.Unix{T: extendedExpiresOn.UTC()},
|
||||
TokenType: tokenType,
|
||||
AuthnSchemeKeyID: authnSchemeKeyID,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +106,11 @@ func (a AccessToken) Key() string {
|
|||
[]string{a.HomeAccountID, a.Environment, a.CredentialType, a.ClientID, a.Realm, a.Scopes},
|
||||
shared.CacheKeySeparator,
|
||||
)
|
||||
// add token type to key for new access tokens types. skip for bearer token type to
|
||||
// preserve fwd and back compat between a common cache and msal clients
|
||||
if !strings.EqualFold(a.TokenType, authority.AccessTokenTypeBearer) {
|
||||
key = strings.Join([]string{key, a.TokenType}, shared.CacheKeySeparator)
|
||||
}
|
||||
return strings.ToLower(key)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ func (m *PartitionedManager) Read(ctx context.Context, authParameters authority.
|
|||
realm := authParameters.AuthorityInfo.Tenant
|
||||
clientID := authParameters.ClientID
|
||||
scopes := authParameters.Scopes
|
||||
authnSchemeKeyID := authParameters.AuthnScheme.KeyID()
|
||||
tokenType := authParameters.AuthnScheme.AccessTokenType()
|
||||
|
||||
// fetch metadata if instanceDiscovery is enabled
|
||||
aliases := []string{authParameters.AuthorityInfo.Host}
|
||||
|
|
@ -57,7 +59,7 @@ func (m *PartitionedManager) Read(ctx context.Context, authParameters authority.
|
|||
|
||||
// errors returned by read* methods indicate a cache miss and are therefore non-fatal. We continue populating
|
||||
// TokenResponse fields so that e.g. lack of an ID token doesn't prevent the caller from receiving a refresh token.
|
||||
accessToken, err := m.readAccessToken(aliases, realm, clientID, userAssertionHash, scopes, partitionKeyFromRequest)
|
||||
accessToken, err := m.readAccessToken(aliases, realm, clientID, userAssertionHash, scopes, partitionKeyFromRequest, tokenType, authnSchemeKeyID)
|
||||
if err == nil {
|
||||
tr.AccessToken = accessToken
|
||||
}
|
||||
|
|
@ -92,7 +94,7 @@ func (m *PartitionedManager) Write(authParameters authority.AuthParams, tokenRes
|
|||
target := strings.Join(tokenResponse.GrantedScopes.Slice, scopeSeparator)
|
||||
userAssertionHash := authParameters.AssertionHash()
|
||||
cachedAt := time.Now()
|
||||
|
||||
authnSchemeKeyID := authParameters.AuthnScheme.KeyID()
|
||||
var account shared.Account
|
||||
|
||||
if len(tokenResponse.RefreshToken) > 0 {
|
||||
|
|
@ -116,6 +118,8 @@ func (m *PartitionedManager) Write(authParameters authority.AuthParams, tokenRes
|
|||
tokenResponse.ExtExpiresOn.T,
|
||||
target,
|
||||
tokenResponse.AccessToken,
|
||||
tokenResponse.TokenType,
|
||||
authnSchemeKeyID,
|
||||
)
|
||||
if authParameters.AuthorizationType == authority.ATOnBehalfOf {
|
||||
accessToken.UserAssertionHash = userAssertionHash // get Hash method on this
|
||||
|
|
@ -215,7 +219,7 @@ func (m *PartitionedManager) aadMetadata(ctx context.Context, authorityInfo auth
|
|||
return m.aadCache[authorityInfo.Host], nil
|
||||
}
|
||||
|
||||
func (m *PartitionedManager) readAccessToken(envAliases []string, realm, clientID, userAssertionHash string, scopes []string, partitionKey string) (AccessToken, error) {
|
||||
func (m *PartitionedManager) readAccessToken(envAliases []string, realm, clientID, userAssertionHash string, scopes []string, partitionKey, tokenType, authnSchemeKeyID string) (AccessToken, error) {
|
||||
m.contractMu.RLock()
|
||||
defer m.contractMu.RUnlock()
|
||||
if accessTokens, ok := m.contract.AccessTokensPartition[partitionKey]; ok {
|
||||
|
|
@ -224,9 +228,11 @@ func (m *PartitionedManager) readAccessToken(envAliases []string, realm, clientI
|
|||
// an issue, however if it does become a problem then we know where to look.
|
||||
for _, at := range accessTokens {
|
||||
if at.Realm == realm && at.ClientID == clientID && at.UserAssertionHash == userAssertionHash {
|
||||
if checkAlias(at.Environment, envAliases) {
|
||||
if isMatchingScopes(scopes, at.Scopes) {
|
||||
return at, nil
|
||||
if at.TokenType == tokenType && at.AuthnSchemeKeyID == authnSchemeKeyID {
|
||||
if checkAlias(at.Environment, envAliases) {
|
||||
if isMatchingScopes(scopes, at.Scopes) {
|
||||
return at, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,39 @@ func isMatchingScopes(scopesOne []string, scopesTwo string) bool {
|
|||
return scopeCounter == len(scopesOne)
|
||||
}
|
||||
|
||||
// needsUpgrade returns true if the given key follows the v1.0 schema i.e.,
|
||||
// it contains an uppercase character (v1.1+ keys are all lowercase)
|
||||
func needsUpgrade(key string) bool {
|
||||
for _, r := range key {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// upgrade a v1.0 cache item by adding a v1.1+ item having the same value and deleting
|
||||
// the v1.0 item. Callers must hold an exclusive lock on m.
|
||||
func upgrade[T any](m map[string]T, k string) T {
|
||||
v1_1Key := strings.ToLower(k)
|
||||
v, ok := m[k]
|
||||
if !ok {
|
||||
// another goroutine did the upgrade while this one was waiting for the write lock
|
||||
return m[v1_1Key]
|
||||
}
|
||||
if v2, ok := m[v1_1Key]; ok {
|
||||
// cache has an equivalent v1.1+ item, which we prefer because we know it was added
|
||||
// by a newer version of the module and is therefore more likely to remain valid.
|
||||
// The v1.0 item may have expired because only v1.0 or earlier would update it.
|
||||
v = v2
|
||||
} else {
|
||||
// add an equivalent item according to the v1.1 schema
|
||||
m[v1_1Key] = v
|
||||
}
|
||||
delete(m, k)
|
||||
return v
|
||||
}
|
||||
|
||||
// Read reads a storage token from the cache if it exists.
|
||||
func (m *Manager) Read(ctx context.Context, authParameters authority.AuthParams) (TokenResponse, error) {
|
||||
tr := TokenResponse{}
|
||||
|
|
@ -89,6 +122,8 @@ func (m *Manager) Read(ctx context.Context, authParameters authority.AuthParams)
|
|||
realm := authParameters.AuthorityInfo.Tenant
|
||||
clientID := authParameters.ClientID
|
||||
scopes := authParameters.Scopes
|
||||
authnSchemeKeyID := authParameters.AuthnScheme.KeyID()
|
||||
tokenType := authParameters.AuthnScheme.AccessTokenType()
|
||||
|
||||
// fetch metadata if instanceDiscovery is enabled
|
||||
aliases := []string{authParameters.AuthorityInfo.Host}
|
||||
|
|
@ -100,7 +135,7 @@ func (m *Manager) Read(ctx context.Context, authParameters authority.AuthParams)
|
|||
aliases = metadata.Aliases
|
||||
}
|
||||
|
||||
accessToken := m.readAccessToken(homeAccountID, aliases, realm, clientID, scopes)
|
||||
accessToken := m.readAccessToken(homeAccountID, aliases, realm, clientID, scopes, tokenType, authnSchemeKeyID)
|
||||
tr.AccessToken = accessToken
|
||||
|
||||
if homeAccountID == "" {
|
||||
|
|
@ -140,6 +175,7 @@ func (m *Manager) Write(authParameters authority.AuthParams, tokenResponse acces
|
|||
clientID := authParameters.ClientID
|
||||
target := strings.Join(tokenResponse.GrantedScopes.Slice, scopeSeparator)
|
||||
cachedAt := time.Now()
|
||||
authnSchemeKeyID := authParameters.AuthnScheme.KeyID()
|
||||
|
||||
var account shared.Account
|
||||
|
||||
|
|
@ -161,6 +197,8 @@ func (m *Manager) Write(authParameters authority.AuthParams, tokenResponse acces
|
|||
tokenResponse.ExtExpiresOn.T,
|
||||
target,
|
||||
tokenResponse.AccessToken,
|
||||
tokenResponse.TokenType,
|
||||
authnSchemeKeyID,
|
||||
)
|
||||
|
||||
// Since we have a valid access token, cache it before moving on.
|
||||
|
|
@ -248,21 +286,27 @@ func (m *Manager) aadMetadata(ctx context.Context, authorityInfo authority.Info)
|
|||
return m.aadCache[authorityInfo.Host], nil
|
||||
}
|
||||
|
||||
func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, clientID string, scopes []string) AccessToken {
|
||||
func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, clientID string, scopes []string, tokenType, authnSchemeKeyID string) AccessToken {
|
||||
m.contractMu.RLock()
|
||||
defer m.contractMu.RUnlock()
|
||||
// TODO: linear search (over a map no less) is slow for a large number (thousands) of tokens.
|
||||
// this shows up as the dominating node in a profile. for real-world scenarios this likely isn't
|
||||
// an issue, however if it does become a problem then we know where to look.
|
||||
for _, at := range m.contract.AccessTokens {
|
||||
for k, at := range m.contract.AccessTokens {
|
||||
if at.HomeAccountID == homeID && at.Realm == realm && at.ClientID == clientID {
|
||||
if checkAlias(at.Environment, envAliases) {
|
||||
if isMatchingScopes(scopes, at.Scopes) {
|
||||
if (strings.EqualFold(at.TokenType, tokenType) && at.AuthnSchemeKeyID == authnSchemeKeyID) || (at.TokenType == "" && (tokenType == "" || tokenType == "Bearer")) {
|
||||
if checkAlias(at.Environment, envAliases) && isMatchingScopes(scopes, at.Scopes) {
|
||||
m.contractMu.RUnlock()
|
||||
if needsUpgrade(k) {
|
||||
m.contractMu.Lock()
|
||||
defer m.contractMu.Unlock()
|
||||
at = upgrade(m.contract.AccessTokens, k)
|
||||
}
|
||||
return at
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m.contractMu.RUnlock()
|
||||
return AccessToken{}
|
||||
}
|
||||
|
||||
|
|
@ -303,15 +347,21 @@ func (m *Manager) readRefreshToken(homeID string, envAliases []string, familyID,
|
|||
// If app is part of the family or if we DO NOT KNOW if it's part of the family, search by family ID, then by client_id (we will know if an app is part of the family after the first token response).
|
||||
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/blob/311fe8b16e7c293462806f397e189a6aa1159769/src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs#L95
|
||||
m.contractMu.RLock()
|
||||
defer m.contractMu.RUnlock()
|
||||
for _, matcher := range matchers {
|
||||
for _, rt := range m.contract.RefreshTokens {
|
||||
for k, rt := range m.contract.RefreshTokens {
|
||||
if matcher(rt) {
|
||||
m.contractMu.RUnlock()
|
||||
if needsUpgrade(k) {
|
||||
m.contractMu.Lock()
|
||||
defer m.contractMu.Unlock()
|
||||
rt = upgrade(m.contract.RefreshTokens, k)
|
||||
}
|
||||
return rt, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.contractMu.RUnlock()
|
||||
return accesstokens.RefreshToken{}, fmt.Errorf("refresh token not found")
|
||||
}
|
||||
|
||||
|
|
@ -333,14 +383,20 @@ func (m *Manager) writeRefreshToken(refreshToken accesstokens.RefreshToken) erro
|
|||
|
||||
func (m *Manager) readIDToken(homeID string, envAliases []string, realm, clientID string) (IDToken, error) {
|
||||
m.contractMu.RLock()
|
||||
defer m.contractMu.RUnlock()
|
||||
for _, idt := range m.contract.IDTokens {
|
||||
for k, idt := range m.contract.IDTokens {
|
||||
if idt.HomeAccountID == homeID && idt.Realm == realm && idt.ClientID == clientID {
|
||||
if checkAlias(idt.Environment, envAliases) {
|
||||
m.contractMu.RUnlock()
|
||||
if needsUpgrade(k) {
|
||||
m.contractMu.Lock()
|
||||
defer m.contractMu.Unlock()
|
||||
idt = upgrade(m.contract.IDTokens, k)
|
||||
}
|
||||
return idt, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
m.contractMu.RUnlock()
|
||||
return IDToken{}, fmt.Errorf("token not found")
|
||||
}
|
||||
|
||||
|
|
@ -379,7 +435,6 @@ func (m *Manager) Account(homeAccountID string) shared.Account {
|
|||
|
||||
func (m *Manager) readAccount(homeAccountID string, envAliases []string, realm string) (shared.Account, error) {
|
||||
m.contractMu.RLock()
|
||||
defer m.contractMu.RUnlock()
|
||||
|
||||
// You might ask why, if cache.Accounts is a map, we would loop through all of these instead of using a key.
|
||||
// We only use a map because the storage contract shared between all language implementations says use a map.
|
||||
|
|
@ -387,11 +442,18 @@ func (m *Manager) readAccount(homeAccountID string, envAliases []string, realm s
|
|||
// a match in multiple envs (envAlias). That means we either need to hash each possible keyand do the lookup
|
||||
// or just statically check. Since the design is to have a storage.Manager per user, the amount of keys stored
|
||||
// is really low (say 2). Each hash is more expensive than the entire iteration.
|
||||
for _, acc := range m.contract.Accounts {
|
||||
for k, acc := range m.contract.Accounts {
|
||||
if acc.HomeAccountID == homeAccountID && checkAlias(acc.Environment, envAliases) && acc.Realm == realm {
|
||||
m.contractMu.RUnlock()
|
||||
if needsUpgrade(k) {
|
||||
m.contractMu.Lock()
|
||||
defer m.contractMu.Unlock()
|
||||
acc = upgrade(m.contract.Accounts, k)
|
||||
}
|
||||
return acc, nil
|
||||
}
|
||||
}
|
||||
m.contractMu.RUnlock()
|
||||
return shared.Account{}, fmt.Errorf("account not found")
|
||||
}
|
||||
|
||||
|
|
@ -405,13 +467,18 @@ func (m *Manager) writeAccount(account shared.Account) error {
|
|||
|
||||
func (m *Manager) readAppMetaData(envAliases []string, clientID string) (AppMetaData, error) {
|
||||
m.contractMu.RLock()
|
||||
defer m.contractMu.RUnlock()
|
||||
|
||||
for _, app := range m.contract.AppMetaData {
|
||||
for k, app := range m.contract.AppMetaData {
|
||||
if checkAlias(app.Environment, envAliases) && app.ClientID == clientID {
|
||||
m.contractMu.RUnlock()
|
||||
if needsUpgrade(k) {
|
||||
m.contractMu.Lock()
|
||||
defer m.contractMu.Unlock()
|
||||
app = upgrade(m.contract.AppMetaData, k)
|
||||
}
|
||||
return app, nil
|
||||
}
|
||||
}
|
||||
m.contractMu.RUnlock()
|
||||
return AppMetaData{}, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ func (t *Client) Credential(ctx context.Context, authParams authority.AuthParams
|
|||
return accesstokens.TokenResponse{}, err
|
||||
}
|
||||
return accesstokens.TokenResponse{
|
||||
TokenType: authParams.AuthnScheme.AccessTokenType(),
|
||||
AccessToken: tr.AccessToken,
|
||||
ExpiresOn: internalTime.DurationTime{
|
||||
T: now.Add(time.Duration(tr.ExpiresInSeconds) * time.Second),
|
||||
|
|
|
|||
|
|
@ -380,6 +380,12 @@ func (c Client) FromSamlGrant(ctx context.Context, authParameters authority.Auth
|
|||
|
||||
func (c Client) doTokenResp(ctx context.Context, authParams authority.AuthParams, qv url.Values) (TokenResponse, error) {
|
||||
resp := TokenResponse{}
|
||||
if authParams.AuthnScheme != nil {
|
||||
trParams := authParams.AuthnScheme.TokenRequestParams()
|
||||
for k, v := range trParams {
|
||||
qv.Set(k, v)
|
||||
}
|
||||
}
|
||||
err := c.Comm.URLFormCall(ctx, authParams.Endpoints.TokenEndpoint, qv, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ type TokenResponse struct {
|
|||
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
|
||||
FamilyID string `json:"foci"`
|
||||
IDToken IDToken `json:"id_token"`
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ const (
|
|||
defaultAPIVersion = "2021-10-01"
|
||||
imdsEndpoint = "http://169.254.169.254/metadata/instance/compute/location?format=text&api-version=" + defaultAPIVersion
|
||||
autoDetectRegion = "TryAutoDetect"
|
||||
AccessTokenTypeBearer = "Bearer"
|
||||
)
|
||||
|
||||
// These are various hosts that host AAD Instance discovery endpoints.
|
||||
|
|
@ -138,6 +139,39 @@ const (
|
|||
ADFS = "ADFS"
|
||||
)
|
||||
|
||||
// AuthenticationScheme is an extensibility mechanism designed to be used only by Azure Arc for proof of possession access tokens.
|
||||
type AuthenticationScheme interface {
|
||||
// Extra parameters that are added to the request to the /token endpoint.
|
||||
TokenRequestParams() map[string]string
|
||||
// Key ID of the public / private key pair used by the encryption algorithm, if any.
|
||||
// Tokens obtained by authentication schemes that use this are bound to the KeyId, i.e.
|
||||
// if a different kid is presented, the access token cannot be used.
|
||||
KeyID() string
|
||||
// Creates the access token that goes into an Authorization HTTP header.
|
||||
FormatAccessToken(accessToken string) (string, error)
|
||||
//Expected to match the token_type parameter returned by ESTS. Used to disambiguate
|
||||
// between ATs of different types (e.g. Bearer and PoP) when loading from cache etc.
|
||||
AccessTokenType() string
|
||||
}
|
||||
|
||||
// default authn scheme realizing AuthenticationScheme for "Bearer" tokens
|
||||
type BearerAuthenticationScheme struct{}
|
||||
|
||||
var bearerAuthnScheme BearerAuthenticationScheme
|
||||
|
||||
func (ba *BearerAuthenticationScheme) TokenRequestParams() map[string]string {
|
||||
return nil
|
||||
}
|
||||
func (ba *BearerAuthenticationScheme) KeyID() string {
|
||||
return ""
|
||||
}
|
||||
func (ba *BearerAuthenticationScheme) FormatAccessToken(accessToken string) (string, error) {
|
||||
return accessToken, nil
|
||||
}
|
||||
func (ba *BearerAuthenticationScheme) AccessTokenType() string {
|
||||
return AccessTokenTypeBearer
|
||||
}
|
||||
|
||||
// AuthParams represents the parameters used for authorization for token acquisition.
|
||||
type AuthParams struct {
|
||||
AuthorityInfo Info
|
||||
|
|
@ -180,6 +214,8 @@ type AuthParams struct {
|
|||
LoginHint string
|
||||
// DomainHint is a directive that can be used to accelerate the user to their federated IdP sign-in page
|
||||
DomainHint string
|
||||
// AuthnScheme is an optional scheme for formatting access tokens
|
||||
AuthnScheme AuthenticationScheme
|
||||
}
|
||||
|
||||
// NewAuthParams creates an authorization parameters object.
|
||||
|
|
@ -188,6 +224,7 @@ func NewAuthParams(clientID string, authorityInfo Info) AuthParams {
|
|||
ClientID: clientID,
|
||||
AuthorityInfo: authorityInfo,
|
||||
CorrelationID: uuid.New().String(),
|
||||
AuthnScheme: &bearerAuthnScheme,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
package version
|
||||
|
||||
// Version is the version of this client package that is communicated to the server.
|
||||
const Version = "1.1.1"
|
||||
const Version = "1.2.0"
|
||||
|
|
|
|||
37
vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
generated
vendored
37
vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
generated
vendored
|
|
@ -47,9 +47,11 @@ import (
|
|||
// For details see https://aka.ms/msal-net-authenticationresult
|
||||
type AuthResult = base.AuthResult
|
||||
|
||||
type AuthenticationScheme = authority.AuthenticationScheme
|
||||
|
||||
type Account = shared.Account
|
||||
|
||||
var errNoAccount = errors.New("no account was specified with public.WithAccount(), or the specified account is invalid")
|
||||
var errNoAccount = errors.New("no account was specified with public.WithSilentAccount(), or the specified account is invalid")
|
||||
|
||||
// clientOptions configures the Client's behavior.
|
||||
type clientOptions struct {
|
||||
|
|
@ -211,6 +213,33 @@ func WithClaims(claims string) interface {
|
|||
}
|
||||
}
|
||||
|
||||
// WithAuthenticationScheme is an extensibility mechanism designed to be used only by Azure Arc for proof of possession access tokens.
|
||||
func WithAuthenticationScheme(authnScheme AuthenticationScheme) interface {
|
||||
AcquireSilentOption
|
||||
AcquireInteractiveOption
|
||||
options.CallOption
|
||||
} {
|
||||
return struct {
|
||||
AcquireSilentOption
|
||||
AcquireInteractiveOption
|
||||
options.CallOption
|
||||
}{
|
||||
CallOption: options.NewCallOption(
|
||||
func(a any) error {
|
||||
switch t := a.(type) {
|
||||
case *acquireTokenSilentOptions:
|
||||
t.authnScheme = authnScheme
|
||||
case *interactiveAuthOptions:
|
||||
t.authnScheme = authnScheme
|
||||
default:
|
||||
return fmt.Errorf("unexpected options type %T", a)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// WithTenantID specifies a tenant for a single authentication. It may be different than the tenant set in [New] by [WithAuthority].
|
||||
// This option is valid for any token acquisition method.
|
||||
func WithTenantID(tenantID string) interface {
|
||||
|
|
@ -260,6 +289,7 @@ func WithTenantID(tenantID string) interface {
|
|||
type acquireTokenSilentOptions struct {
|
||||
account Account
|
||||
claims, tenantID string
|
||||
authnScheme AuthenticationScheme
|
||||
}
|
||||
|
||||
// AcquireSilentOption is implemented by options for AcquireTokenSilent
|
||||
|
|
@ -310,6 +340,7 @@ func (pca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts
|
|||
RequestType: accesstokens.ATPublic,
|
||||
IsAppCache: false,
|
||||
TenantID: o.tenantID,
|
||||
AuthnScheme: o.authnScheme,
|
||||
}
|
||||
|
||||
return pca.base.AcquireTokenSilent(ctx, silentParameters)
|
||||
|
|
@ -482,6 +513,7 @@ func (pca Client) RemoveAccount(ctx context.Context, account Account) error {
|
|||
type interactiveAuthOptions struct {
|
||||
claims, domainHint, loginHint, redirectURI, tenantID string
|
||||
openURL func(url string) error
|
||||
authnScheme AuthenticationScheme
|
||||
}
|
||||
|
||||
// AcquireInteractiveOption is implemented by options for AcquireTokenInteractive
|
||||
|
|
@ -628,6 +660,9 @@ func (pca Client) AcquireTokenInteractive(ctx context.Context, scopes []string,
|
|||
authParams.DomainHint = o.domainHint
|
||||
authParams.State = uuid.New().String()
|
||||
authParams.Prompt = "select_account"
|
||||
if o.authnScheme != nil {
|
||||
authParams.AuthnScheme = o.authnScheme
|
||||
}
|
||||
res, err := pca.browserLogin(ctx, redirectURL, authParams, o.openURL)
|
||||
if err != nil {
|
||||
return AuthResult{}, err
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue