rksajib
rksajib

Reputation: 180

Authorization Code Flow with Pkce OpendIdDict

I'm trying to implement the authorization code flow with PKCE using OpenIdDict

The basic flow is as follows:

Expected behavior: Output AccessToken

Actual behavior: It tried to redirect to the redirect url

Here is my start-up code

.AddCookie(AuthConstants.ConsumerAppBiometricAuthenticationScheme, config =>
            {
                config.Cookie.HttpOnly = true;
                //options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
                config.Cookie.SameSite = SameSiteMode.Lax;
                config.Cookie.Name = AuthConstants.ConsumerAppBiometricAuthenticationScheme;
                config.LoginPath = new PathString("/api/BiometricAuthentication/BiometricChallenge");
                config.ExpireTimeSpan = TimeSpan.FromMinutes(Clients.DefaultAccessTokenLifeTime);
                config.SlidingExpiration = true;
            })

Here is my code inside authorization endpoint

         var authScheme = AuthConstants.ConsumerAppBiometricAuthenticationScheme;
 var result = await HttpContext.AuthenticateAsync(authScheme);
 if (!result.Succeeded)
     return Challenge(authScheme!);
 var phone = result.Principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.MobilePhone);

 var claimsPrincipal = await _authorizationService.GrantAuthorizationCode(new AuthorizationCodeCommand
 {
     ClientId = request.ClientId,
     Scopes = ImmutableArray<string>.Empty,
     UserName = phone.Value,
     Audiences = request.Audiences
 });

 // Signing in with the OpenIddict authentication scheme trigger OpenIddict to issue a code (which can be exchanged for an access token)
 return SignIn(claimsPrincipal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

Here is my code inside the Authentication

     [HttpGet]
 public async Task<BiometricChallengeView> BiometricChallenge(string returnUrl)
 {
     var query = Helper.GetQueryParams(HttpContext.Request.Host.ToString(), returnUrl);
     var phoneNumber = query.Get(AuthConstants.PhoneNumber);
     var challenge = await _authenticationService.GetChallenge(phoneNumber);
     return new BiometricChallengeView
     {
         ReturnUrl = returnUrl,
         UserName = phoneNumber,
         Challenge = challenge
     };

 }

 [HttpPost]
 public async Task<IActionResult> BiometricChallenge(BiometricChallengeView encryptedChallenge)
 {
     await _authenticationService.VerifyChallenge(encryptedChallenge.UserName, encryptedChallenge.Challenge);
     await SignInAsync(encryptedChallenge.UserName);
     return Redirect(encryptedChallenge.ReturnUrl);
 }

 private async Task SignInAsync(string phone)
 {
     const string scheme = AuthConstants.ConsumerAppBiometricAuthenticationScheme;
     var claims = new List<Claim>
     {
         new(ClaimTypes.MobilePhone, phone),
         new(ClaimTypes.PrimarySid, Guid.NewGuid().ToString())
     };
     var claimsIdentity = new ClaimsIdentity(claims, scheme);

     await HttpContext.SignInAsync(scheme, new ClaimsPrincipal(claimsIdentity));
 }

Upvotes: 0

Views: 258

Answers (1)

K&#233;vin Chalet
K&#233;vin Chalet

Reputation: 42000

It's the expected behavior: the code flow is a two-step process that first consists in redirecting the user agent back to the client application with an intermediate token called "authorization code": the access token is only delivered during a second step, via a backchannel API request called "token request".

Upvotes: 0

Related Questions