From 06ce6ba7393712f696f5df08cb4962da71581680 Mon Sep 17 00:00:00 2001 From: Mohanjith Sudirikku Hannadige Date: Thu, 28 Nov 2024 23:06:33 +0200 Subject: [PATCH] fix: username password flow (#536) * fix: username password flow * test: unit tests for confidential username password auth --- apps/confidential/confidential.go | 48 ++++++++++++++++++++++++++ apps/confidential/confidential_test.go | 4 +++ 2 files changed, 52 insertions(+) diff --git a/apps/confidential/confidential.go b/apps/confidential/confidential.go index 57d0e277..5b375794 100644 --- a/apps/confidential/confidential.go +++ b/apps/confidential/confidential.go @@ -429,6 +429,7 @@ func WithClaims(claims string) interface { AcquireByAuthCodeOption AcquireByCredentialOption AcquireOnBehalfOfOption + AcquireByUsernamePasswordOption AcquireSilentOption AuthCodeURLOption options.CallOption @@ -437,6 +438,7 @@ func WithClaims(claims string) interface { AcquireByAuthCodeOption AcquireByCredentialOption AcquireOnBehalfOfOption + AcquireByUsernamePasswordOption AcquireSilentOption AuthCodeURLOption options.CallOption @@ -450,6 +452,8 @@ func WithClaims(claims string) interface { t.claims = claims case *acquireTokenOnBehalfOfOptions: t.claims = claims + case *acquireTokenByUsernamePasswordOptions: + t.claims = claims case *acquireTokenSilentOptions: t.claims = claims case *authCodeURLOptions: @@ -496,6 +500,7 @@ func WithTenantID(tenantID string) interface { AcquireByAuthCodeOption AcquireByCredentialOption AcquireOnBehalfOfOption + AcquireByUsernamePasswordOption AcquireSilentOption AuthCodeURLOption options.CallOption @@ -504,6 +509,7 @@ func WithTenantID(tenantID string) interface { AcquireByAuthCodeOption AcquireByCredentialOption AcquireOnBehalfOfOption + AcquireByUsernamePasswordOption AcquireSilentOption AuthCodeURLOption options.CallOption @@ -517,6 +523,8 @@ func WithTenantID(tenantID string) interface { t.tenantID = tenantID case *acquireTokenOnBehalfOfOptions: t.tenantID = tenantID + case *acquireTokenByUsernamePasswordOptions: + t.tenantID = tenantID case *acquireTokenSilentOptions: t.tenantID = tenantID case *authCodeURLOptions: @@ -592,6 +600,46 @@ func (cca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts return cca.base.AcquireTokenSilent(ctx, silentParameters) } +// acquireTokenByUsernamePasswordOptions contains optional configuration for AcquireTokenByUsernamePassword +type acquireTokenByUsernamePasswordOptions struct { + claims, tenantID string + authnScheme AuthenticationScheme +} + +// AcquireByUsernamePasswordOption is implemented by options for AcquireTokenByUsernamePassword +type AcquireByUsernamePasswordOption interface { + acquireByUsernamePasswordOption() +} + +// AcquireTokenByUsernamePassword acquires a security token from the authority, via Username/Password Authentication. +// NOTE: this flow is NOT recommended. +// +// Options: [WithClaims], [WithTenantID] +func (cca Client) AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username, password string, opts ...AcquireByUsernamePasswordOption) (AuthResult, error) { + o := acquireTokenByUsernamePasswordOptions{} + if err := options.ApplyOptions(&o, opts); err != nil { + return AuthResult{}, err + } + authParams, err := cca.base.AuthParams.WithTenant(o.tenantID) + if err != nil { + return AuthResult{}, err + } + authParams.Scopes = scopes + authParams.AuthorizationType = authority.ATUsernamePassword + authParams.Claims = o.claims + authParams.Username = username + authParams.Password = password + if o.authnScheme != nil { + authParams.AuthnScheme = o.authnScheme + } + + token, err := cca.base.Token.UsernamePassword(ctx, authParams) + if err != nil { + return AuthResult{}, err + } + return cca.base.AuthResultFromToken(ctx, authParams, token, true) +} + // acquireTokenByAuthCodeOptions contains the optional parameters used to acquire an access token using the authorization code flow. type acquireTokenByAuthCodeOptions struct { challenge, claims, tenantID string diff --git a/apps/confidential/confidential_test.go b/apps/confidential/confidential_test.go index 9a9c9ee1..1036c4f7 100644 --- a/apps/confidential/confidential_test.go +++ b/apps/confidential/confidential_test.go @@ -964,6 +964,8 @@ func TestWithClaims(t *testing.T) { ar, err = client.AcquireTokenByCredential(ctx, tokenScope, WithClaims(test.claims)) case "obo": ar, err = client.AcquireTokenOnBehalfOf(ctx, "assertion", tokenScope, WithClaims(test.claims)) + case "password": + ar, err = client.AcquireTokenByUsernamePassword(ctx, tokenScope, "username", "password", WithClaims(test.claims)) default: t.Fatalf("test bug: no test for " + method) } @@ -1222,6 +1224,8 @@ func TestWithInstanceDiscovery(t *testing.T) { ar, err = client.AcquireTokenByCredential(ctx, tokenScope) case "obo": ar, err = client.AcquireTokenOnBehalfOf(ctx, "assertion", tokenScope) + case "password": + ar, err = client.AcquireTokenByUsernamePassword(ctx, tokenScope, "username", "password") default: t.Fatal("test bug: no test for " + method) }