skip to Main Content

I have successfully implemented OAuth 2.0 authorization into a .NET 8 service and was able to consume it in both Postman and Swagger (using pkce).

However when it came time to consume it through another .NET service, I encountered issues.

I have been able to obtain the token, but I still get a http 403 error when attempting to consume the service endpoint.

This is my Authorize() method:

var authority = $"https://login.microsoftonline.com/{_config.TennantId}/oauth2/v2.0/token";

var app = ConfidentialClientApplicationBuilder
              .Create(_config.ClientId)
              .WithClientSecret(_config.ClientSecret)
              .WithAuthority(authority)
              .Build();

var result = await app.AcquireTokenForClient(new string[] { $"{_config.Scopes}" })
                      .ExecuteAsync();

This is the authorization configuration on the target app:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApi(builder.Configuration);

This is the controller of the target app:

[Authorize]
[RequiredScope("WriteOperations")]
[ApiController]
public class CustomersController : ControllerBase

I know that for Postman and swagger one needs to provide a redirect Url. But the documentation I found for backend to backend flows, doesn’t include any mention of one.

What am I doing wrong and how can I fix this?

2

Answers


  1. Chosen as BEST ANSWER

    For everyone dealing with this issue, when you create a permission in the App Registration in EntraID, you need to also provide admin consent to that permission. It's necessary for the Client Credentials flow, which the code in my question uses. I've made request before and after granting admin consent, in order to make sure that was the issue. It'll work without for Authorization Code flow, though.

    As about missing scope, which was mentioned by the submitted answer above and the comment to the post, that's not the case. Client Credentials flow only allows for .default scope.


  2. The 403 error usually occurs if the access token does not contain required scopes to call the API.

    • The AcquireTokenForClient flow generates access token without user interaction and performs a client-to-client flow.
    • Based on your scenario, you need to generate access token using user interactive flow which will include scope claim in the access token to access the API.
    • Hence, you have to make use of PKCE code flow to generate the token.
    • As you are making use of PKCE flow I believe you created SPA application.

    Created a Microsoft Entra SPA application and exposed an API, added scope like below:

    enter image description here

    Granted API permissions:

    enter image description here

    For sample, generated tokens via Postman:

    https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
    
    client_id:ClientID
    grant_type:authorization_code
    code:code
    redirect_uri:https://jwt.ms
    code_verifier:S256
    scope:api://xxx/spaapp.access
    

    enter image description here

    To do the same via code, you need to make use of AcquireTokenByAuthorizationCodeParameterBuilder WithPkceCodeVerifier flow not AcquireTokenForClient flow or any other user interactive flow based on your requirement refer this MsDoc

    public Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder AcquireTokenByAuthorizationCode (System.Collections.Generic.IEnumerable<string> scopes, string authorizationCode);
    

    For complete code, refer this GitHub blog.

    • Or if you are configured application as WEB, make use of AcquireTokenByAuthorizationCode Refer this SO Thread by me.

    Make sure to decode the access token and check the scp and aud claim is populated correctly:

    enter image description here

    Reference:

    How to implement a PKCE code challenge in C# | Nicola Iarocci

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search