SDK-2768-net-support-central-auth-tokens#555
Open
mehmet-yoti wants to merge 5 commits into
Open
Conversation
Build() used Validation.NotNull(_keyPair, nameof(_keyPair)) which throws ArgumentNullException with the private field name exposed in the parameter. The test Build_MissingKeyPairShouldThrow expects InvalidOperationException, consistent with the rest of the builder's Build() validation pattern (missing sdkId and empty scopes both throw InvalidOperationException).
There was a problem hiding this comment.
Pull request overview
This PR introduces an authentication strategy abstraction (IAuthStrategy) to support both existing signed-request auth and new central-auth bearer token auth across the SDK, plus a central-auth token generator (JWT client assertion → OAuth2 client_credentials).
Changes:
- Added
IAuthStrategywith concrete implementations:SignedRequestAuthStrategy,BearerTokenAuthStrategy, andNoAuthStrategy. - Updated request construction and service/client APIs to accept an auth strategy (and added bearer-token factory methods for clients).
- Added central-auth token generation via
AuthenticationTokenGenerator+ fluentAuthenticationTokenGeneratorBuilder, with accompanying tests.
Reviewed changes
Copilot reviewed 26 out of 27 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| test/Yoti.Auth.Tests/Web/SignedRequestAuthStrategyTests.cs | New unit tests for signed-request strategy behavior and guards. |
| test/Yoti.Auth.Tests/Web/RequestBuilderTests.cs | Updated tests for new auth-strategy path and mutual exclusion with keypair. |
| test/Yoti.Auth.Tests/Web/NoAuthStrategyTests.cs | New tests for no-auth strategy semantics. |
| test/Yoti.Auth.Tests/Web/BearerTokenAuthStrategyTests.cs | New tests for bearer token strategy headers and validation. |
| test/Yoti.Auth.Tests/DocScan/DocScanServiceTests.cs | Updated Doc Scan service tests to use IAuthStrategy rather than sdkId/keyPair params. |
| test/Yoti.Auth.Tests/DocScan/DocScanClientTests.cs | Added tests for DocScanClient.FromBearerToken(...). |
| test/Yoti.Auth.Tests/DigitalIdentityClientTests.cs | Added tests for DigitalIdentityClient.FromBearerToken(...) and bearer-token limitations. |
| test/Yoti.Auth.Tests/DigitalIdentityClientEngineTests.cs | Updated engine tests to pass IAuthStrategy. |
| test/Yoti.Auth.Tests/DigitalIdentity/DigitalIdentityServiceTests.cs | Updated Digital Identity service tests to use IAuthStrategy. |
| test/Yoti.Auth.Tests/CentralAuth/AuthenticationTokenGeneratorTests.cs | New tests for OAuth token generation request/response handling. |
| test/Yoti.Auth.Tests/CentralAuth/AuthenticationTokenGeneratorBuilderTests.cs | New tests for builder validation and configuration options. |
| src/Yoti.Auth/Web/SignedRequestAuthStrategy.cs | New signed-request strategy encapsulating digest + nonce/timestamp generation. |
| src/Yoti.Auth/Web/RequestBuilder.cs | Added WithAuthStrategy, mutual exclusion checks, and strategy-driven query/header injection. |
| src/Yoti.Auth/Web/NoAuthStrategy.cs | New no-auth strategy returning no headers/query params. |
| src/Yoti.Auth/Web/IAuthStrategy.cs | New authentication strategy contract used by clients/services. |
| src/Yoti.Auth/Web/HeadersFactory.cs | Added strategy-based header injection helper. |
| src/Yoti.Auth/Web/BearerTokenAuthStrategy.cs | New bearer token strategy adding Authorization: Bearer <token>. |
| src/Yoti.Auth/DocScan/DocScanService.cs | Refactored Doc Scan service methods to accept IAuthStrategy and optionally include sdkId. |
| src/Yoti.Auth/DocScan/DocScanClient.cs | Client now uses IAuthStrategy; added bearer-token factory method. |
| src/Yoti.Auth/DigitalIdentityClientEngine.cs | Engine methods updated to accept IAuthStrategy. |
| src/Yoti.Auth/DigitalIdentityClient.cs | Client now uses IAuthStrategy; added bearer-token factory methods. |
| src/Yoti.Auth/DigitalIdentity/DigitalIdentityService.cs | Service refactored to accept IAuthStrategy; added signed-request requirement for receipt decryption. |
| src/Yoti.Auth/Constants/Api.cs | Added Authorization header constant and default auth API URL. |
| src/Yoti.Auth/CentralAuth/AuthenticationTokenResponse.cs | New DTO for auth token endpoint responses. |
| src/Yoti.Auth/CentralAuth/AuthenticationTokenGeneratorBuilder.cs | New builder for configuring AuthenticationTokenGenerator. |
| src/Yoti.Auth/CentralAuth/AuthenticationTokenGenerator.cs | New implementation for JWT client assertion and token acquisition. |
| .gitignore | Ignore generated coverage XML files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+37
to
+43
| public AuthenticationTokenGeneratorBuilder WithScopes(IEnumerable<string> scopes) | ||
| { | ||
| if (scopes == null) | ||
| throw new ArgumentNullException(nameof(scopes)); | ||
| _scopes.AddRange(scopes); | ||
| return this; | ||
| } |
Comment on lines
+27
to
+31
| public async Task<AuthenticationTokenResponse> GetToken(HttpClient httpClient) | ||
| { | ||
| string jwt = BuildJwt(); | ||
| string scope = string.Join(" ", _scopes); | ||
|
|
Comment on lines
99
to
102
| Validation.NotNull(httpClient, nameof(httpClient)); | ||
| Validation.NotNull(apiUrl, nameof(apiUrl)); | ||
| Validation.NotNull(sdkId, nameof(sdkId)); | ||
| Validation.NotNull(keyPair, nameof(keyPair)); | ||
| Validation.NotNull(authStrategy, nameof(authStrategy)); | ||
|
|
Comment on lines
+321
to
+322
| string result = endpointBuilder.ToString().TrimEnd('&').TrimEnd('?'); | ||
| return result.EndsWith("?", StringComparison.Ordinal) ? result.TrimEnd('?') : result; |
… code
- WithScopes: validate each scope entry for null/whitespace before adding to avoid invalid OAuth scope strings
- WithScope: validate the scope argument before adding
- AuthenticationTokenGenerator.GetToken: add null check for httpClient to give a clear exception instead of NullReferenceException from PostAsync
- BearerTokenAuthStrategy: upgrade IsNullOrEmpty to IsNullOrWhiteSpace to reject whitespace-only tokens that would produce an invalid Authorization header
- DigitalIdentityService.CreateQrCode: add explicit validation for sessionId and qrRequestPayload to prevent malformed endpoints and serializing null to "null"
- RequestBuilder: remove redundant EndsWith("?") check after TrimEnd('?') — the condition can never be true; simplify to a single TrimEnd chain
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
IAuthStrategy)BearerTokenAuthStrategysendsAuthorization: Bearer <token>; existingSignedRequestAuthStrategyencapsulates RSA digest + nonce/timestampDigitalIdentityClientandDocScanClientgain new constructors accepting a bearer token stringAuthenticationTokenGeneratorissues PS384 JWT → OAuth2client_credentialsgrant to obtain access tokens, with a fluent builder