Add the application permissions documentation page

This commit is contained in:
Kévin Chalet
2018-02-12 00:54:40 +01:00
parent 14f1f37359
commit 4c62ff83a1
5 changed files with 175 additions and 91 deletions

View File

@@ -0,0 +1,153 @@
# Application permissions
Starting with RC2, OpenIddict includes an optional feature codenamed "app permissions" that allows
controlling and limiting the OAuth2/OpenID Connect features a client application is able to use.
3 categories of permissions are currently supported:
- Endpoint permissions
- Grant type/flow permissions
- Scope permissions.
> Configuring application permissions is recommended when dealing with
third-party clients, to ensure they can only use the features they need.
## Endpoint permissions
### Definition
Endpoint permissions limit the endpoints a client application can use.
> If no endpoint permission is explicitly granted, the client application
is allowed to use all the endpoints enabled in `Startup.ConfigureServices()`.
### Supported permissions
| Endpoint | Constant |
|:---------------------------:|:---------------------------------------------------------:|
| Authorization endpoint | `OpenIddictConstants.Permissions.Endpoints.Authorization` |
| Introspection endpoint | `OpenIddictConstants.Permissions.Endpoints.Introspection` |
| Logout/end session endpoint | `OpenIddictConstants.Permissions.Endpoints.Logout` |
| Revocation endpoint | `OpenIddictConstants.Permissions.Endpoints.Revocation` |
| Token endpoint | `OpenIddictConstants.Permissions.Endpoints.Token` |
### Example
In the following example, the `mvc` application is allowed to use the authorization, logout and
token endpoints but will get an error when trying to send an introspection or revocation request:
```csharp
if (await manager.FindByClientIdAsync("mvc") == null)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
DisplayName = "MVC client application",
PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") },
RedirectUris = { new Uri("http://localhost:53507/signin-oidc") },
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Token
}
});
}
```
## Grant type permissions
### Definition
Grant type permissions limit the flows a client application is allowed to use.
> If no grant type permission is explictly attached to an application, all the flows enabled in `Startup.ConfigureServices()`
can be freely used by the application (as long as the authorization or token endpoint permissions are granted).
### Supported permissions
| Grant type | Constant |
|:-----------------------:|:--------------------------------------------------------------:|
| Authorization code flow | `OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode` |
| Client credentials flow | `OpenIddictConstants.Permissions.GrantTypes.ClientCredentials` |
| Implicit flow | `OpenIddictConstants.Permissions.GrantTypes.Implicit` |
| Password flow | `OpenIddictConstants.Permissions.GrantTypes.Password` |
| Refresh token flow | `OpenIddictConstants.Permissions.GrantTypes.RefreshToken` |
To add a custom flow permission, you can use the following pattern:
```csharp
OpenIddictConstants.Permissions.Prefixes.GrantType + "custom_flow_name"
```
### Example
In the following example, the `postman` application can only use the authorization code flow
while `console` is restricted to the `password` and `refresh_token` flows:
```csharp
if (await manager.FindByClientIdAsync("postman") == null)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "postman",
DisplayName = "Postman",
RedirectUris = { new Uri("https://www.getpostman.com/oauth2/callback") },
Permissions =
{
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode
}
});
}
if (await manager.FindByClientIdAsync("console") == null)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "console",
DisplayName = "Console",
Permissions =
{
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken
}
});
}
```
## Scope permissions
### Definition
Scope permissions limit the scopes (standard or custom) a client application is allowed to use.
> Like the other permissions, **scope permissions are optional**: if no scope permission is explictly attached,
a client application is free to specify any scope in the authorization or token requests.
> The `openid` and `offline_access` scopes are special-cased by OpenIddict and don't require explicit permissions.
### Example
In the following sample, the `angular` client is allowed to request the `address`,
`profile` and `custom` scopes: any other scope will result in an error being returned.
```csharp
if (await manager.FindByClientIdAsync("angular") == null)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "angular",
DisplayName = "Angular",
RedirectUris = { new Uri("https://localhost:34422/callback") },
Permissions =
{
OpenIddictConstants.Permissions.Prefixes.Scope +
OpenIdConnectConstants.Scopes.Address,
OpenIddictConstants.Permissions.Prefixes.Scope +
OpenIdConnectConstants.Scopes.Profile,
OpenIddictConstants.Permissions.Prefixes.Scope + "custom"
}
});
}
```

10
features/index.md Normal file
View File

@@ -0,0 +1,10 @@
<div class="row">
<div class="col-md-4">
<div class="panel panel-default" style="min-height: 120px;">
<div class="panel-body">
<p><strong><a href="application-permissions.md">Application permissions</a></strong></p>
<p>Learn how to leverage permissions to control the OIDC features a client is allowed to use.</p>
</div>
</div>
</div>
</div>

4
features/toc.yml Normal file
View File

@@ -0,0 +1,4 @@
- name: Introduction
href: index.md
- name: Application permissions
href: application-permissions.md

View File

@@ -95,28 +95,6 @@ private async Task UpdateOpenIddictTablesAsync(IServiceProvider services)
application.RedirectUris = new JArray(addresses).ToString(Formatting.None); application.RedirectUris = new JArray(addresses).ToString(Formatting.None);
} }
// Grant the application all the permissions. Don't hesitate to update
// the list to only grant the permissions really needed by the application.
if (string.IsNullOrEmpty(application.Permissions))
{
var permissions = new[]
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
OpenIddictConstants.Permissions.GrantTypes.Implicit,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken
};
application.Permissions = new JArray(permissions).ToString(Formatting.None);
}
} }
// If you use a different entity type or a custom key, // If you use a different entity type or a custom key,
@@ -161,76 +139,12 @@ public void Configure(IApplicationBuilder app)
Run your application. Once it's correctly started, stop it and remove the migration script. Run your application. Once it's correctly started, stop it and remove the migration script.
## If necessary, update your code to grant applications the required permissions ## Optionally, update your code to grant applications the minimum required permissions
If you have code that relies on `OpenIddictApplicationManager.CreateAsync(OpenIddictApplicationDescriptor)`, Starting with RC2, OpenIddict includes an optional feature codenamed "app permissions" that allows
make sure that the appropriate set of permissions is granted. controlling and limiting the OAuth2/OpenID Connect features a client application is able to use.
For instance, to allow a client application to use the password and refresh token flows, you must grant the following permissions: To learn more about this feature, read the [Application permissions documentation](~/features/application-permissions.md).
```csharp
var descriptor = new OpenIddictApplicationDescriptor
{
// ...
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken
}
};
await manager.CreateAsync(descriptor);
```
For the authorization code flow, the following permissions are required:
```csharp
var descriptor = new OpenIddictApplicationDescriptor
{
// ...
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode
}
};
await manager.CreateAsync(descriptor);
```
For custom flows, use the `OpenIddictConstants.Permissions.Prefixes.GrantType` constant:
```csharp
var descriptor = new OpenIddictApplicationDescriptor
{
// ...
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.Prefixes.GrantType + "google_token_exchange"
}
};
await manager.CreateAsync(descriptor);
```
If your application uses introspection or revocation, these endpoints must also be enable. E.g:
```csharp
var descriptor = new OpenIddictApplicationDescriptor
{
// ...
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Revocation
}
};
await manager.CreateAsync(descriptor);
```
# List of changes (for applications using custom stores) # List of changes (for applications using custom stores)

View File

@@ -3,3 +3,6 @@
- name: Migration guide - name: Migration guide
href: guide/migration.md href: guide/migration.md
- name: Features
href: features/index.md