swagger-api / swagger-api/swagger-ui

Supporting Azure AD OAuth 2.0 Client Credentials Grant Flow

Open
#5,223 7 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

cat: auth type: support
Dominant language
JavaScript
Stars
29k
Forks
9.3k
Avg merge
2d 23h
Merged PRs (30d)
25

Description

Azure AD OAuth 2.0 Client Credentials Grant Flow (https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow)

Content & configuration

Swagger/OpenAPI definition: 2.0

Swashbuckle.AspNetCore 4.0.1

Swagger-UI configuration options:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc(resourceName, new Info {Title = urn});
c.CustomSchemaIds(i => i.FullName);
c.AddSecurityDefinition
(
oAuth2SecurityDefinitionName,
new OAuth2Scheme
{
Type = oAuth2,
Flow = application,
TokenUrl = tokenUrl,
Scopes = new Dictionary<string, string> { { oAuth2SecurityDefinitionName, userImpersonation } }
}
);
c.AddSecurityRequirement(new Dictionary<string, IEnumerable> {{oAuth2SecurityDefinitionName, new[] {userImpersonation}}});
});

SwaggerUI({
c.OAuthClientId(clientId);
c.OAuthClientSecret(clientSecret);
c.OAuthRealm(uri);
c.OAuthAppName(resourceName);
c.OAuthScopeSeparator(value: " ");
c.SwaggerEndpoint($"/swagger/{resourceName}/swagger.json", resourceName);
})

Is your feature request related to a problem?

The Swagger UI OAuth2 Application Flow does not support the Azure AD OAuth 2.0 Client Credentials Grant Flow for the V1 endpoint.

This is due to two things:

  1. The client_id and client_secret needs to be sent in the request body, instead of a Basic Auth Header, which now is the case.

  2. Microsoft also has an other key/value that needs to be included in the request body, namely 'resource' which is either the AppId (Guid) or the Uri (e.g. https://the-azure-resource-display-name.azurewebsites.net") for the Azure Resource, which is likely also the OAuthRealm.

  3. I have not been able to test if you also get both Delegated Permissions (aka Scopes, e.g. user_impersonation) and the Application Permissions (aka Roles) in the Token, since I don't come that far, but it needs to be ensured as well.

Describe the solution you'd like

Either you implement a separate hard coded flow for this like the ones you already have:

swagger-ui/src/core/plugins/auth/actions.js

export const authorizeApplication = ( auth ) => ( { authActions } ) => {
let { schema, scopes, name, clientId, clientSecret } = auth
let headers = {
Authorization: "Basic " + btoa(clientId + ":" + clientSecret)
}
let form = {
grant_type: "client_credentials",
scope: scopes.join(scopeSeparator)
}

Add something like this:

export const authorizeAzureActiveDirectoryApplication = ( auth ) => ( { authActions } ) => {
let { schema, scopes, name, clientId, clientSecret } = auth
let form = {
grant_type: "client_credentials",
client_id : "your-client-id"
client_secret : "your-client-secret"
resource : "appId/appUri"
scope: scopes.join(scopeSeparator)
}

Or a more generic solution would be to add configuration for this.

You have done something like this in the Swagger UI OAuth2 Password Flow, where you can choose whether to send credentials in the Header or the Body.

Preferably this could also be done directly in the StartUp configuration looking something like this:

SwaggerUI({
c.OAuthClientId(clientId);
c.OAuthClientSecret(clientSecret);
c.SendOAuthClientCredentialsIn(BasicAuthHeader/RequestBody)
c.OAuthRealm(uri);
c.OAuthAppName(resourceName);
c.OAuthScopeSeparator(value: " ");
c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> {});
c.OAuthAdditionalRequestBodyParams(new Dictionary<string, string> {{"resource", uri}});
c.SwaggerEndpoint($"/swagger/{resourceName}/swagger.json", resourceName);
})

Describe alternatives you've considered

Using the implicit flow, which works, but then requires that you configure your Azure Resource to allow the Implicit Flow, that you have a User and not just an Application, that the User has the same access, scopes and roles as the Client Application has as well as that and that user impersonation is allowed.

Additional context

Azure AD OAuth 2.0 Client Credentials Grant Flow (https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow) is the recommended way of doing service to service calls using client credentials (shared secret or certificate) in Azure according to Microsoft and it would be great to be able to use the same Auth process in Swagger that is used in the actual flow.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in swagger-ui/src/core/plugins/auth/actions.js by reviewing authorizeApplication and the existing OAuth2 password-flow credential handling. Trace how SwaggerUI OAuth options reach the token request. Done means Azure AD v1 client-credentials requests can send credentials and the resource value in the request body while retaining the configured scopes and application permissions.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, openapi
Domain
api, authentication
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.