wertzui
wertzui

Reputation: 5720

Getting Microsoft.Identity (former AzureAD) to work with Swagger

I have an ASP.Net 5 Web API which is secured using The Microsoft.identity.Web package, so it is backed by Azure Active Directory. The authentication in the API itself is working fine and without any problems.

I'm struggling when I want to get the authorization to work inside Swagger UI. I'm using the Authorization code flow and everything seems fine at first (I get to the Microsoft login screen, can enter my credentials and receive an authorization code).

However after Swagger UI got the authorization code, it calls the token endpoint at https://login.microsoftonline.com/organizations/oauth2/v2.0/token. The response from that call is 99% percent fine, except that it is missing the Allow-Origin-Header so the response is blocked by the browser itself and cannot reach the Swagger UI JavaScript which would then set the token it received from that response.

What am I missing here to get that header in the response?

This is the code in my Startup.cs

services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("msid", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
        Type = Microsoft.OpenApi.Models.SecuritySchemeType.OAuth2,
        Flows = new Microsoft.OpenApi.Models.OpenApiOAuthFlows
        {
            AuthorizationCode = new Microsoft.OpenApi.Models.OpenApiOAuthFlow
            {
                AuthorizationUrl = new System.Uri("https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize"),
                TokenUrl = new System.Uri("https://login.microsoftonline.com/organizations/oauth2/v2.0/token"),
                Scopes = new Dictionary<string, string>
                {
                    { "api://myClientId/access", "access" }
                }
            }
        }
    });

    c.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
    {
        {
            new Microsoft.OpenApi.Models.OpenApiSecurityScheme
            {
                Reference = new Microsoft.OpenApi.Models.OpenApiReference {Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, Id = "msid" }
            },
            new [] { "api://myClientId/access" }
        }
    });
});

This is the request which is sent from Swagger UI to https://login.microsoftonline.com/organizations/oauth2/v2.0/token

POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Connection: keep-alive
Content-Length: 1086
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Chromium";v="94", "Microsoft Edge";v="94", ";Not A Brand";v="99"
Accept: application/json, text/plain, */*
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4585.0 Safari/537.36 Edg/94.0.972.0
sec-ch-ua-platform: "Windows"
Origin: https://localhost:5003
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://localhost:5003/
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en;q=0.8,en-US;q=0.7

grant_type=authorization_code&code=hereIsMyLongAuthorizationCode&redirect_uri=https%3A%2F%2Flocalhost%3A5003%2Fswagger%2Foauth2-redirect.html

This is the response

HTTP/1.1 200 OK
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
x-ms-request-id: 683dc687-7211-400b-ab02-bccdc6e9ba00
x-ms-ests-server: 2.1.11898.12 - WEULR1 ProdSlices
report-to: {"group":"network-errors","max_age":86400,"endpoints":[{"url":"https://identity.nel.measure.office.net/api/report?catId=GW+estsfd+dub2"}]}
nel: {"report_to":"network-errors","max_age":86400,"success_fraction":0.001,"failure_fraction":1.0}
Set-Cookie: fpc=...; expires=Fri, 03-Sep-2021 13:57:11 GMT; path=/; secure; HttpOnly; SameSite=None
Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; samesite=none; httponly
Set-Cookie: stsservicecookie=estsfd; path=/; secure; samesite=none; httponly
Referrer-Policy: strict-origin-when-cross-origin
Date: Wed, 04 Aug 2021 13:57:10 GMT
Content-Length: 1763

{"token_type":"Bearer","scope":"api://myClientId/access","expires_in":3599,"ext_expires_in":3599,"access_token":"theToken"}

Upvotes: 3

Views: 3042

Answers (1)

wertzui
wertzui

Reputation: 5720

The problem was that I was using the AuthorizationCode-Flow which is only suitable for backend applications, because the client secret needs to be transmitted there.

The correct way was to use the Implicit-Flow while keeping everything else the same. That flow is intended for JS applications where it is impossible to securely send a client secret without the user being able to see it.

Upvotes: 0

Related Questions