Skip to content

Commit

Permalink
Expanded PAR documentation
Browse files Browse the repository at this point in the history
- Add store reference material
- Describe usage mechanics
- Link to sample
- Add client and global configs to appropriate pages
  • Loading branch information
josephdecock committed Jan 25, 2024
1 parent 1245053 commit be66b2d
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 4 deletions.
2 changes: 1 addition & 1 deletion IdentityServer/v7/docs/content/data/ef.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ This options class contains properties to control the operational store and *Per
Allows setting the default database schema name for all the tables in the *PersistedGrantDbContext*.

*EnableTokenCleanup*
Indicates whether expired grants will be automatically cleaned up from the database. The default is *false*.
Indicates whether expired grants and pushed authorization requests will be automatically cleaned up from the database. The default is *false*.

*RemoveConsumedTokens* [added in 5.1]
Indicates whether consumed grants will be automatically cleaned up from the database. The default is *false*.
Expand Down
11 changes: 11 additions & 0 deletions IdentityServer/v7/docs/content/reference/models/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,14 @@ Added in 6.3.0.

An optional URI that can be used to [initiate login](https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin) from the IdentityServer host or a third party. This is most commonly used to create a client application portal within the IdentityServer host. Defaults to null.


## Pushed Authorization Requests
Added in 7.0.0

* ***RequirePushedAuthorization***

Controls if this client requires PAR. PAR is required if either the global configuration is enabled or if the client's flag is enabled (this can't be used to opt out of the global configuration). This defaults to *false*, which means the global configuration will be used.

* ***PushedAuthorizationLifetime***

Controls the lifetime of pushed authorization requests for a client. If this lifetime is set, it takes precedence over the global configuration. This defaults to *null*, which means the global configuration is used.
19 changes: 18 additions & 1 deletion IdentityServer/v7/docs/content/reference/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ Endpoint settings, including flags to disable individual endpoints and support f

Enables the backchannel authentication endpoint. Defaults to true.

* ***EnablePushedAuthorizationEndpoint***

Enables the pushed authorization endpoint. Defaults to true.

* ***EnableJwtRequestUri***
Enables the *request_uri* parameter for JWT-Secured Authorization Requests. This allows the JWT to be passed by reference. Disabled by default, due to the security implications of enabling the request_uri parameter (see [RFC 9101 section 10.4](https://datatracker.ietf.org/doc/rfc9101/)).
Expand Down Expand Up @@ -685,7 +689,7 @@ Settings for [server-side sessions]({{<ref "/ui/server_side_sessions">}}). Added
## DPoP
Added in 6.3.0.

Demonstration of Proof-of-Possession settings. Available on the *DPoP* property of the *IdentityServerOptions* object.
Demonstration of Proof-of-Possession settings. Available on the *DPoP* property of the *IdentityServerOptions* object.

* ***ProofTokenValidityDuration***

Expand All @@ -694,3 +698,16 @@ Demonstration of Proof-of-Possession settings. Available on the *DPoP* property
* ***ServerClockSkew***

Clock skew used in validating DPoP proof token expiration using a server-generated nonce value. Defaults to *0*.

## Pushed Authorization Requests
Added in 7.0.0

Pushed Authorization Requests (PAR) settings. Available on the *PushedAuthorization* property of the *IdentityServerOptions* object.

* ***Required***

Causes PAR to be required globally. Defaults to *false*.

* ***Lifetime***

Controls the lifetime of pushed authorization requests. The pushed authorization request's lifetime begins when the request to the PAR endpoint is received, and is validated until the authorize endpoint returns a response to the client application. Note that user interaction, such as entering credentials or granting consent, may need to occur before the authorize endpoint can do so. Setting the lifetime too low will likely cause login failures for interactive users, if pushed authorization requests expire before those users complete authentication. Some security profiles, such as the FAPI 2.0 Security Profile recommend an expiration within 10 minutes to prevent attackers from pre-generating requests. To balance these constraints, this lifetime defaults to 10 minutes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: "Pushed Authorization Request Store"
weight: 110
---

The pushed authorization request store is responsible for creating, retrieving, and
consuming pushed authorization requests.

#### Duende.IdentityServer.Stores.IPushedAuthorizationRequestStore

```cs
/// <summary>
/// The interface for a service that stores pushed authorization requests.
/// </summary>
public interface IPushedAuthorizationRequestStore
{
/// <summary>
/// Stores the pushed authorization request.
/// </summary>
/// <param name="pushedAuthorizationRequest">The request.</param>
/// <returns></returns>
Task StoreAsync(PushedAuthorizationRequest pushedAuthorizationRequest);

/// <summary>
/// Consumes the pushed authorization request, indicating that it should not
/// be used again. Repeated use could indicate some form of replay attack,
/// but also could indicate that an end user refreshed their browser or
/// otherwise retried a request that consumed the pushed authorization
/// request.
/// </summary>
/// <param name="referenceValueHash">The hash of the reference value of the
/// pushed authorization request. The reference value is the identifier
/// within the request_uri parameter.</param>
/// <returns></returns>
Task ConsumeByHashAsync(string referenceValueHash);

/// <summary>
/// Gets the pushed authorization request.
/// </summary>
/// <param name="referenceValueHash">The hash of the reference value of the
/// pushed authorization request. The reference value is the identifier
/// within the request_uri parameter.</param>
/// <returns>The pushed authorization request, or null if the request does
/// not exist or was previously consumed.
/// </returns>
Task<PushedAuthorizationRequest?> GetByHashAsync(string referenceValueHash);
}
```

#### Duende.IdentityServer.Models.PushedAuthorizationRequest

```cs
/// <summary>
/// Represents a persisted Pushed Authorization Request.
/// </summary>
public class PushedAuthorizationRequest
{
/// <summary>
/// The hash of the identifier within this pushed request's request_uri
/// value. Request URIs that IdentityServer produces take the form
/// urn:ietf:params:oauth:request_uri:{ReferenceValue}.
/// </summary>
public string ReferenceValueHash { get; set; }

/// <summary>
/// The UTC time at which this pushed request will expire. The Pushed
/// request will be used throughout the authentication process, beginning
/// when it is passed to the authorization endpoint by the client, and then
/// subsequently after user interaction, such as login and/or consent occur.
/// If the expiration time is exceeded before a response to the client can
/// be produced, IdentityServer will raise an error, and the user will be
/// redirected to the IdentityServer error page.
/// </summary>
public DateTime ExpiresAtUtc { get; set; }

/// <summary>
/// The data protected content of the pushed authorization request.
/// </summary>
public string Parameters { get; set; }
}
```
23 changes: 21 additions & 2 deletions IdentityServer/v7/docs/content/tokens/par.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,33 @@ Pushing the authorization parameters also keeps request URLs short. Authorize pa

The use of PAR is encouraged by the [FAPI working group](https://openid.net/wg/fapi/) within the OpenID Foundation. For example, [the FAPI2.0 Security Profile](https://openid.bitbucket.io/fapi/fapi-2_0-security-profile.html) requires the use of PAR. This security profile is used by many of the groups working on open banking (primarily in Europe), in health care, and in other industries with high security requirements.

Duende.IdentityServer includes support for PAR in the Business Edition or higher license.
## Licensing
Duende.IdentityServer includes support for PAR in the Business Edition or higher license. In the starter edition, PAR requests will not be processed and instead log errors. If you have a starter edition license, you should disable the *EnablePushedAuthorizationEndpoint* flag so that discovery indicates that your IdentityServer does not support PAR:

```cs
services.AddIdentityServer(options =>
{
options.Endpoints.EnablePushedAuthorizationEndpoint = false;
})
```

## Client Usage
Using PAR is similar to other flows that use the authorization endpoint, but it adds an initial back-channel request to a new protocol endpoint for pushed authorization requests. This endpoint requires client authentication and accepts POSTed form-urlencoded data containing all of the same parameters that are accepted at the authorize endpoint.

The result of the PAR request is JSON containing an identifier (the *request_uri* property) and expiration information (the *expires_in* property). Clients then send that identifier to the authorize endpoint instead of the parameters that were just pushed. From there, the OAuth or OIDC flow continues as normal. For example, in the authorization code flow, the user will be redirected to login and other UI pages as necessary before being redirected back to the client with an authorization code which the client subsequently exchanges for tokens.

A sample of how to implement this flow in an ASP.NET application is available [here]({{< ref "/samples/basics#par" >}}).

## Data Store
Pushed authorization requests are stored in the *IPushedAuthorizationRequestStore*, which includes methods to store, retrieve, and consume pushed requests. Pushed requests that are not used are removed by the token cleanup job.

## Configuration
- *IdentityServerOptions* now includes the *PushedAuthorization* property to configure PAR.
- *PushedAuthorizationOptions.Required* causes par to be required globally. This defaults to *false*.
- *PushedAuthorizationOptions.Required* causes PAR to be required globally. This defaults to *false*.
- *PushedAuthorizationOptions.Lifetime* controls the lifetime of pushed authorization requests. The pushed authorization request's lifetime begins when the request to the PAR endpoint is received, and is validated until the authorize endpoint returns a response to the client application. Note that user interaction, such as entering credentials or granting consent, may need to occur before the authorize endpoint can do so. Setting the lifetime too low will likely cause login failures for interactive users, if pushed authorization requests expire before those users complete authentication. Some security profiles, such as the FAPI 2.0 Security Profile recommend an expiration within 10 minutes to prevent attackers from pre-generating requests. To balance these constraints, this lifetime defaults to 10 minutes.
- *PushedAuthorizationOptions.AllowUnregisteredPushedRedirectUris* controls whether clients may use redirect uris that were not previously registered. This is a relaxation of security guidance that is specifically allowed by the PAR specification because the pushed authorization requests are authenticated. It defaults to *false*.
- The *Client* configuration object now includes two new properties to configure PAR on a per-client basis.
- *Client.RequirePushedAuthorization* controls if this client requires PAR. PAR is required if either the global configuration is enabled or if the client's flag is enabled (this can't be used to opt out of the global configuration). This defaults to *false*, which means the global configuration will be used.
- *Client.PushedAuthorizationLifetime* controls the lifetime of pushed authorization requests for a client. If this lifetime is set, it takes precedence over the global configuration. This defaults to *null*, which means the global configuration is used.
- The *EndpointOptions* now includes a new flag to enable or disable the PAR endpoint: *EnablePushedAuthorizationEndpoint*, which defaults to *true*.

0 comments on commit be66b2d

Please sign in to comment.