Skip to content

Commit

Permalink
Updated the READMEs
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Klaus committed Oct 11, 2024
1 parent ab49fce commit e07f983
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
28 changes: 22 additions & 6 deletions OpenIdDict.Server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@

A custom build Identity Server that implements OAuth 2 [Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) with [PKCE](https://oauth.net/2/pkce/) to serve other client apps as a trusted authority and perform authentication from a linked _Identity Provider_ (a specified tenant of Azure AD).

## 2. Run it
As a bonus for opening the API to integration with third-parties, it also implements the [Client Credentials Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow).

## 2. Run the sample app

**Prerequisite**: an _Azure AD_ tenant supporting authentication.

1. Configure `appsettings.json` (by setting parameters directly in the file or view [user secrets](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets)):
1. To support _Azure Entra ID_ authentication, configure the `appsettings.json` (by setting parameters directly in the file or via the [user secrets](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets)):
- `AzureAd:Tenant` – the name of your tenant (e.g. _contoso.onmicrosoft.com_) or its tenant ID (a GUID). Sometime it's referred as the _issuer_<br>The parameter is used in forming a set of HTTP endpoints for the _Identity Provider_ (Azure AD in our case). E.g. `https://login.microsoftonline.com/{TENANT}/oauth2/v2.0/authorize`.
- `AzureAd:ClientId` – the _Application (client) ID_ (a GUID) of the _App Registration_.
- `AzureAd:Scope` – The requested scope (also called [delegated permission](https://learn.microsoft.com/en-au/azure/active-directory/develop/permissions-consent-overview)), for the client apps to obtain an access token. Note that all APIs must publish a minimum of one scope and this app is using just one for simplicity.
2. Launch it.
2. Launch the Server.
3. Try the two available end-points. `/anonymous` must return a HTTP 200 code, while `/protected` gives a 401.
4. Pass the Swagger authentication.<br> It will pop up a new tab with a bunch of redirects that brings the user to the Azure AD login page and will close it on successful authentication.
4. Pass the Swagger authentication. Either of the 2 provided options:
1. The _Authorization Code Flow_ (for users) to authenticate via the linked _Azure Entra ID_.<br>It will pop up a new tab with a bunch of redirects that brings the user to the _Azure Entra ID_ login page and will close it on successful authentication.
2. The _Client Credentials Flow_ (for API integration) to authenticate via the `client_id` and `client_secret` only.
5. Try `/protected` end-point and it must return a HTTP 200 code.

## 3. Implementation
Expand All @@ -23,13 +27,25 @@ The API has just two end-points:
- `/anonymous` that always returns HTTP code 200 on any request.
- `/protected` that requires user to authenticate and provide a self-issued Bearer token. Otherwise, it returns HTTP code 401 Unauthorized.

Handling OAuth 2 [Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) with [PKCE](https://oauth.net/2/pkce/) is implemented with using [OpenIdDict](https://github.com/openiddict/openiddict-core) NuGet package with the key implementation is in `HandleAuthorizationRequestContext` handler of its 'degraded mode' (see [this article](https://kevinchalet.com/2020/02/18/creating-an-openid-connect-server-proxy-with-openiddict-3-0-s-degraded-mode/) from the author of the library on detailed implementation).
Handling the _OAuth 2_ is implemented with using [OpenIdDict](https://github.com/openiddict/openiddict-core) NuGet package with the key implementation is in `HandleAuthorizationRequestContext` handler of its 'degraded mode' (see [this article](https://kevinchalet.com/2020/02/18/creating-an-openid-connect-server-proxy-with-openiddict-3-0-s-degraded-mode/) from the author of the library on detailed implementation).

The authentication client is implemented by [NSwag](https://github.com/RicoSuter/NSwag).

The authentication client is implemented by [NSwag](https://github.com/RicoSuter/NSwag):
From the consumer's perspective, the _Authorization Code Flow_ looks like:
1. The user gets redirected to `/authorize` route.<br>
E.g. `/connect/authorize?response_type=code&client_id=TestApp&redirect_uri=https%3A%2F%2Flocalhost%3A5003%2Fswagger%2Foauth2-redirect.html&scope=openid&state={STATE}&realm=realm&code_challenge={CODE_CHALLENGE}&code_challenge_method=S256`
2. If a relevant user identity cookie not found,
1. the user gets redirected further to the login page of the linked _Identity Provider_ (for Azure AD it's `https://login.microsoftonline.com/{TENANT}/oauth2/v2.0/authorize`).
2. on successful authentication withing the tenant, the user gets redirected back to the Auth Gateway to continue the authentication/authorisation process.
3. On successful authentication/authorisation, the user gets redirected back to Swagger<br> `/swagger/oauth2-redirect.html?code={CODE}&session_state={RANDOM_STATE}`,<br>where `CODE` is a reference token to the auth code stored in memory cache on the server.
4. Then _NSwag_'s JavaScript exchanges the received _code_ to an _access token_ by running a `POST` request to `/token`.

The _Client Credentials Flow_ is simpler and involves only a single call to the `/token` route. E.g.:
```bash
curl --location '/connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'grant_type=client_credentials' \
--data 'scope=profile' \
--data 'client_id=TestApp' \
--data 'client_secret=test'
```
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ The code uses _Azure AD_ as the linked _Identity Provider_ (for the identity che
![Transparent Auth Gateway](./auth-gateway-enterprise-apps.png)

The implemented protocols:
- OAuth 2 [Authorisation Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) ([RFC 6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1)) with [Proof Key for Code Exchange](https://www.oauth.com/oauth2-servers/pkce/) ([RFC 7636](https://www.rfc-editor.org/rfc/rfc7636))
- OpenID Connect ([OIDC](https://openid.net/connect/)).
- OAuth 2 [Authorisation Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) ([RFC 6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1)) with [Proof Key for Code Exchange](https://www.oauth.com/oauth2-servers/pkce/) ([RFC 7636](https://www.rfc-editor.org/rfc/rfc7636)).
- OAuth 2 [Client Credentials Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow).

# Code structure
There are 3 projects:

- [AzureADAuthClient](./AzureADAuthClient) – a quick way to ensure that _Azure AD_ authentication is configured. Uses Swagger UI to acquire a token and the standard `Microsoft.Identity` way to validate the token on WebAPI.
- [OpenIdDict.Server](./OpenIdDict.Server) – a bespoke _Transparent Auth Gateway_ to confirm the user's identity from the linked provider and authorise the user (issue own _access token_) according to the bespoke rules:
- implements OAuth 2 [Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) with [PKCE](https://oauth.net/2/pkce/) to serve other client apps as the trusted authority;
- perform authentication from the linked _Identity Provider_ (a specified tenant of Azure AD).
- implements OAuth 2 flows to serve as the trusted authorization authority to other client apps:
- [Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) with [PKCE](https://oauth.net/2/pkce/) for user authorization;
- [Client Credentials Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow) for API integration;
- for users authorization, it perform authentication from the linked _Identity Provider_ (a specified tenant of Azure AD).
- [OpenIdDict.Client.Api](./OpenIdDict.Client.Api) – A Web API app that validates the _access token_ issued by the Auth Gateway (`OpenIdDict.Server`). Contains:
- Swagger front-end to request the token and run HTTP requests;
- test API end-points.
Expand Down

0 comments on commit e07f983

Please sign in to comment.