public async Task <PaymentInitiationApiProfileResponse> CreateAsync(PaymentInitiationApiProfilePublic apiProfile) { // Check for existing API profile. // ApiProfile existingProfile = await _apiProfileRepo // .GetAsync(apiProfile.Id); // if (!(existingProfile is null)) // { // throw new Exception("There is already a API Profile with specified ID."); // } // Create and store persistent object ApiProfile persistentApiProfile = new ApiProfile( id: apiProfile.Id, bankClientProfileId: apiProfile.BankClientProfileId, apiVersion: apiProfile.ApiVersion, baseUrl: apiProfile.BaseUrl); await _apiProfileRepo.UpsertAsync(persistentApiProfile); await _dbContextService.SaveChangesAsync(); // Return response object return(new PaymentInitiationApiProfileResponse( id: persistentApiProfile.Id, bankClientProfileId: persistentApiProfile.BankClientProfileId, apiVersion: persistentApiProfile.ApiVersion, baseUrl: persistentApiProfile.BaseUrl)); }
public async Task GetAsync_ByExpression_GetByUniqueProperty(int count) { var items = Enumerable.Range(1, count) .Select(i => new DomesticConsent { Id = i.ToString() }).ToList(); foreach (var dc in items) { await _repo.UpsertAsync(dc); } _dbMultiEntityMethods.SaveChangesAsync().Wait(); var q = await _repo.GetAsync(x => x.Id == count.ToString()); var results = q.ToList(); results.Should().HaveCount(1); results[0].Should().Be(items.Last()); }
public async Task <BankClientProfileResponse> CreateAsync(BankClientProfilePublic bankClientProfile) { bankClientProfile.ArgNotNull(nameof(bankClientProfile)); // Load relevant objects SoftwareStatementProfile softwareStatementProfile = _softwareStatementProfileService.GetSoftwareStatementProfile( bankClientProfile.SoftwareStatementProfileId); // STEP 1 // Compute claims associated with Open Banking client // Get OpenID Connect configuration info OpenIdConfiguration openIdConfiguration = await GetOpenIdConfigurationAsync(bankClientProfile.IssuerUrl); new OpenBankingOpenIdConfigurationResponseValidator().Validate(openIdConfiguration) .RaiseErrorOnValidationError(); // Create claims for client reg OpenBankingClientRegistrationClaims registrationClaims = Factories.CreateRegistrationClaims( issuerUrl: bankClientProfile.IssuerUrl, sProfile: softwareStatementProfile, concatScopes: false); BankClientRegistrationClaimsOverrides registrationClaimsOverrides = bankClientProfile.BankClientRegistrationClaimsOverrides; if (!(registrationClaimsOverrides is null)) { if (!(registrationClaimsOverrides.RequestAudience is null)) { registrationClaims.Aud = registrationClaimsOverrides.RequestAudience; } } BankClientRegistrationClaims persistentRegistrationClaims = _mapper.Map <BankClientRegistrationClaims>(registrationClaims); // STEP 2 // Check for existing Open Banking client for issuer URL // If we have an Open Banking client with the same issuer URL we will check if the claims match. // If they do, we will re-use this client. // Otherwise we will return an error as only support a single client per issuer URL at present. IQueryable <BankClientProfile> clientList = await _bankClientProfileRepo .GetAsync(c => c.IssuerUrl == bankClientProfile.IssuerUrl); BankClientProfile existingClient = clientList .SingleOrDefault(); if (existingClient is object) { if (existingClient.BankClientRegistrationClaims != persistentRegistrationClaims) { throw new Exception( "There is already a client for this issuer URL but it cannot be re-used because claims are different."); } } // STEP 3 // Create new Open Banking client by posting JWT BankClientProfile client; if (existingClient is null) { JwtFactory jwtFactory = new JwtFactory(); string jwt = jwtFactory.CreateJwt( profile: softwareStatementProfile, claims: registrationClaims, useOpenBankingJwtHeaders: false); OpenBankingClientRegistrationResponse registrationResponse = await new HttpRequestBuilder() .SetMethod(HttpMethod.Post) .SetUri(openIdConfiguration.RegistrationEndpoint) .SetContent(jwt) .SetContentType("application/jwt") .Create() .RequestJsonAsync <OpenBankingClientRegistrationResponse>( client: _apiClient, requestContentIsJson: false); BankClientRegistrationData openBankingClientResponse = new BankClientRegistrationData { ClientId = registrationResponse.ClientId, ClientIdIssuedAt = registrationResponse.ClientIdIssuedAt, ClientSecret = registrationResponse.ClientSecret, ClientSecretExpiresAt = registrationResponse.ClientSecretExpiresAt }; // Create and store Open Banking client BankClientProfile newClient = _mapper.Map <BankClientProfile>(bankClientProfile); client = await PersistOpenBankingClient( value : newClient, openIdConfiguration : openIdConfiguration, registrationClaims : registrationClaims, openBankingRegistrationData : openBankingClientResponse); await _dbMultiEntityMethods.SaveChangesAsync(); } else { client = existingClient; } // Return return(new BankClientProfileResponse(client)); }
public async Task <PaymentConsentResponse> CreateAsync(DomesticPaymentConsent consent) { consent.ArgNotNull(nameof(consent)); // Load relevant objects ApiProfile apiProfile = await _apiProfileRepo.GetAsync(consent.ApiProfileId) ?? throw new KeyNotFoundException("The API Profile does not exist."); BankClientProfile bankClientProfile = await _bankClientProfileRepo.GetAsync(apiProfile.BankClientProfileId) ?? throw new KeyNotFoundException( "The Bank Client Profile does not exist."); SoftwareStatementProfile softwareStatementProfile = _softwareStatementProfileService.GetSoftwareStatementProfile( bankClientProfile.SoftwareStatementProfileId); // Get client credentials grant (we will not cache token for now but simply use to POST consent) TokenEndpointResponse tokenEndpointResponse = await PostClientCredentialsGrant(scope : "payments", client : bankClientProfile); // TODO: validate the response??? // Create new Open Banking consent by posting JWT JwtFactory jwtFactory = new JwtFactory(); OBWriteDomesticConsentResponse4 consentResponse; switch (apiProfile.ApiVersion) { case ApiVersion.V3P1P1: OBWriteDomesticConsent2 newDomesticConsent = _mapper.Map <OBWriteDomesticConsent2>(consent.DomesticConsent); OBWriteDomesticConsentResponse2 rawConsentResponse = await PostDomesticConsent <OBWriteDomesticConsent2, OBWriteDomesticConsentResponse2>( jwtFactory : jwtFactory, softwareStatementProfile : softwareStatementProfile, consent : newDomesticConsent, apiProfile : apiProfile, bankClientProfile : bankClientProfile, tokenEndpointResponse : tokenEndpointResponse); consentResponse = _mapper.Map <OBWriteDomesticConsentResponse4>(rawConsentResponse); break; case ApiVersion.V3P1P2: throw new ArgumentOutOfRangeException(); case ApiVersion.V3P1P4: consentResponse = await PostDomesticConsent <OBWriteDomesticConsent4, OBWriteDomesticConsentResponse4>( jwtFactory : jwtFactory, softwareStatementProfile : softwareStatementProfile, consent : consent.DomesticConsent, apiProfile : apiProfile, bankClientProfile : bankClientProfile, tokenEndpointResponse : tokenEndpointResponse); break; default: throw new ArgumentOutOfRangeException(); } // Generate URL for user auth string consentId = consentResponse.Data.ConsentId; string redirectUrl = softwareStatementProfile.DefaultFragmentRedirectUrl; if (redirectUrl == "") { redirectUrl = bankClientProfile.BankClientRegistrationClaims.RedirectUris[0]; } OAuth2RequestObjectClaims oAuth2RequestObjectClaims = Factories.CreateOAuth2RequestObjectClaims( openBankingClient: bankClientProfile, redirectUrl: redirectUrl, scope: new[] { "openid", "payments" }, intentId: consentId); string requestObjectJwt = jwtFactory.CreateJwt( profile: softwareStatementProfile, claims: oAuth2RequestObjectClaims, useOpenBankingJwtHeaders: false); Dictionary <string, string> keyValuePairs = new Dictionary <string, string> { { "response_type", oAuth2RequestObjectClaims.ResponseType }, { "client_id", oAuth2RequestObjectClaims.ClientId }, { "redirect_uri", oAuth2RequestObjectClaims.RedirectUri }, { "scope", oAuth2RequestObjectClaims.Scope }, { "request", requestObjectJwt }, { "nonce", oAuth2RequestObjectClaims.Nonce }, { "state", oAuth2RequestObjectClaims.State } }; string queryString = keyValuePairs.ToUrlEncoded(); string authUrl = bankClientProfile.OpenIdConfiguration.AuthorizationEndpoint + "?" + queryString; // Create and store persistent object string domesticConsentId = Guid.NewGuid().ToString(); DomesticConsent value = new DomesticConsent { State = oAuth2RequestObjectClaims.State, SoftwareStatementProfileId = bankClientProfile.SoftwareStatementProfileId, IssuerUrl = bankClientProfile.IssuerUrl, ApiProfileId = apiProfile.Id, ObWriteDomesticConsent = consent.DomesticConsent, TokenEndpointResponse = null, Id = domesticConsentId, BankId = consentId }; await _domesticConsentRepo.UpsertAsync(value); await _dbMultiEntityMethods.SaveChangesAsync(); return(new PaymentConsentResponse { AuthUrl = authUrl, ConsentId = domesticConsentId }); }