Skip to content

Commit

Permalink
Merge pull request #1250 from authts/improve-doc
Browse files Browse the repository at this point in the history
improve documentation
  • Loading branch information
pamapa authored Nov 17, 2023
2 parents b5d3233 + 7755013 commit cb52133
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 61 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ available [here](docs/migration.md).
Implements the following OAuth 2.0 protocols and supports
[OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html):

- [Authorization Code Grant](https://oauth.net/2/grant-types/authorization-code/)
with [PKCE](https://oauth.net/2/pkce/)
- [Resource Owner Password Credentials Grant](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3); however, read the [security concerns](docs/ropc.md) before using this flow
- [Refresh Token Grant](https://oauth.net/2/grant-types/refresh-token/)
- [Authorization Code Grant with Proof Key for Code Exchange (PKCE)](docs/protocols/authorization-code-grant-with-pkce.md)
- [Authorization Code Grant](docs/protocols/authorization-code-grant.md)
- [Resource Owner Password Credentials (ROPC) Grant](docs/protocols/resource-owner-password-credentials-grant.md)
- [Refresh Token Grant](docs/protocols/refresh-token-grant.md)
- [Silent Refresh Token in iframe Flow](docs/protocols/silent-refresh-token-in-iframe-flow.md)

## Table of Contents

Expand Down
37 changes: 21 additions & 16 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,25 @@ with you use to use the library:
The remainder of this document will primarily focus on the
[UserManager](classes/UserManager.html).

## UserManager

### Configuration
# Principle of function
To understand how to use this library see here:
- [Authorization Code Grant with Proof Key for Code Exchange (PKCE)](https://github.com/authts/oidc-client-ts/blob/main/docs/protocols/authorization-code-grant-with-pkce.md)
- [Authorization Code Grant](https://github.com/authts/oidc-client-ts/blob/main/docs/protocols/authorization-code-grant.md)
- [Resource Owner Password Credentials (ROPC) Grant](https://github.com/authts/oidc-client-ts/blob/main/docs/protocols/resource-owner-password-credentials-grant.md)
- [Refresh Token Grant](https://github.com/authts/oidc-client-ts/blob/main/docs/protocols/refresh-token-grant.md)
- [Silent Refresh Token in iframe Flow](https://github.com/authts/oidc-client-ts/blob/main/docs/protocols/silent-refresh-token-in-iframe-flow.md)

# UserManager

## Configuration
The [UserManager](classes/UserManager.html) constructor requires a settings
object as a parameter:

- [UserManagerSettings](interfaces/UserManagerSettings.html) which extends
- [OidcClientSettings](interfaces/OidcClientSettings.html)

#### Required settings

### Required settings
- [authority](interfaces/OidcClientSettings.html#authority): The URL of the
OIDC/OAuth2 provider.
- [client_id](interfaces/OidcClientSettings.html#client_id): Your client
Expand All @@ -35,8 +42,7 @@ object as a parameter:
URI of your client application to receive a response from the OIDC/OAuth2
provider.

#### Provider settings if CORS not supported on OIDC/OAuth2 provider metadata endpoint

### Provider settings if CORS not supported on OIDC/OAuth2 provider metadata endpoint
The [authority](interfaces/OidcClientSettings.html#authority) URL setting is
used to make HTTP requests to discover more information about the OIDC/OAuth2
provider and populate a `metadata` property on the settings. If the server does
Expand All @@ -52,8 +58,7 @@ provider:
- [metadataSeed](interfaces/UserManagerSettings.html#metadataSeed) can be used
to seed or add additional values to the results of the discovery request.

### Events

## Events
The [UserManager](classes/UserManager.html) will raise various events about the
user's session:

Expand All @@ -71,11 +76,11 @@ mgr.events.addAccessTokenExpiring(function() {
});
```

## User
# User
The [User](classes/User.html) type is returned from the [UserManager](classes/UserManager.html)'s [getUser](classes/UserManager.html#getUser) API.


## Logging
# Logging
The oidc-client-ts library supports logging. You can set a logger by assigning `Oidc.Log.logger` to anything that supports a `info`, `warn`, and `error` methods that accept a params array. By default, no logger is configured.

The `console` object in the browser supports these, so a common way to easily
Expand All @@ -89,7 +94,7 @@ Also, logging has levels so you can control the verbosity by calling
`Oidc.Log.setLevel()` with one of `Oidc.Log.NONE`, `Oidc.Log.ERROR`,
`Oidc.Log.WARN`, or `Oidc.Log.INFO`. The default is `Oidc.Log.INFO`.

## Provider specific settings
# Provider specific settings
Additional provider specific settings may be needed for a flawless operation:

**Amazon Cognito**
Expand All @@ -104,7 +109,7 @@ const mgr = new UserManager({
```


## Custom state in user object
# Custom state in user object
In case you would like to add additional data into the [User](classes/User.html) object, you can do so during the initial sign-in request.

```javascript
Expand All @@ -117,7 +122,7 @@ After successful sign-in the custom state is part of the [User](classes/User.htm

This custom state should not be confused with the URL state parameter. The latter is internally used to match against the authentication state object to finish the authentication process.

## Custom state in request url
# Custom state in request url
If you would like to encode a custom state string in the sign in request url, you can do so with the `url_state` parameter. You may want to do this in order to pass user state to the authentication server and/or a proxy and return that state as part of the response.

```javascript
Expand All @@ -128,13 +133,13 @@ mgr.signinRedirect({ url_state: 'custom url state' })
The `url_state` will be appended to the opaque, unique value created by the library when sending the request. It should survive the round trip to your authentication server and will be part of the [User](classes/User.html#url_state) object as `url_state`.


## Projects using oidc-client
# Projects using oidc-client-ts

- [React context provider](https://github.com/authts/react-oidc-context)
- [Angular sample](https://github.com/authts/sample-angular-oidc-client-ts)
- [Chrome service worker](https://github.com/Alino/OIDC-client-ts-chromium-sample)


## Training
# Training

- [Securing Angular Apps with OpenID and OAuth2](https://noyes.me/ng-openid-oauth2)
- [Securing Angular Apps with OpenID Connect and OAuth2](https://www.pluralsight.com/courses/openid-and-oauth2-securing-angular-apps)
14 changes: 9 additions & 5 deletions docs/migration.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
## oidc-client-ts v2.4.0 → oidc-client-ts v3.0.0

The API is largely backwards-compatible. The merge claims behavior has been improved.
The API is largely backwards-compatible.

The "crypto-js" software library has been removed; the native crypto/crypto.subtle module built into the browser is instead used. All modern browser are expected to support it. If need to support older browsers stay with v2.4!

The behavior of merging claims has been improved.

### [OidcClientSettings](https://authts.github.io/oidc-client-ts/interfaces/OidcClientSettings.html)

- the following deprecated properties were **removed**:
- `clockSkewInSeconds` unused since 2.0.0
- `userInfoJwtIssuer` unused since 2.0.0
- `refreshTokenCredentials` use `fetchRequestCredentials` since 2.1.0
- `clockSkewInSeconds`
- `userInfoJwtIssuer`
- `refreshTokenCredentials` use `fetchRequestCredentials`
- the `mergeClaims` has been replaced by `mergeClaimsStrategy`
- if the previous behavior is needed `mergeClaimsStrategy: { array: "merge" }` can be used
- if the previous behavior is required `mergeClaimsStrategy: { array: "merge" }` comes close to it
- default of `response_mode` changed from `query` → `undefined`


Expand Down
2 changes: 0 additions & 2 deletions docs/oidc-client-ts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,6 @@ export class UserManager {
readonly settings: UserManagerSettingsStore;
// (undocumented)
protected _signin(args: CreateSigninRequestArgs, handle: IWindow, verifySub?: string): Promise<User>;
// (undocumented)
signinCallback(url?: string): Promise<User | void>;
// (undocumented)
protected _signinEnd(url: string, verifySub?: string): Promise<User>;
Expand All @@ -984,7 +983,6 @@ export class UserManager {
protected _signinStart(args: CreateSigninRequestArgs, handle: IWindow): Promise<NavigateResponse>;
// (undocumented)
protected _signout(args: CreateSignoutRequestArgs, handle: IWindow): Promise<SignoutResponse>;
// (undocumented)
signoutCallback(url?: string, keepOpen?: boolean): Promise<void>;
// (undocumented)
protected _signoutEnd(url: string): Promise<SignoutResponse>;
Expand Down
37 changes: 37 additions & 0 deletions docs/protocols/authorization-code-grant-with-pkce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Authorization Code Grant with Proof Key for Code Exchange (PKCE)

The authorization code protocol is part of OAuth 2.0 (defined in [OAuth 2.0 RFC 7636](https://tools.ietf.org/html/rfc7636)). It involves the exchange of an authorization code for a token. This is the recommend authorization code flow in the [OAuth 2.1 draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-10).


## Principle of function
```mermaid
---
title: Authorization Code Grant with Proof Key for Code Exchange (PKCE)
---
sequenceDiagram
actor User
User->>App: Click sign-in link (1)
activate App
Note left of App: Generate code_verifier and<br/>code_challenge
App->>Identity Provider: Authorization code request & code_challenge (2)
deactivate App
Identity Provider-->>User: Redirect to login/authorization prompt (3)
User-->>Identity Provider: Authenticate (3)
Identity Provider->>App: Authorization code (3)
activate App
App->>Identity Provider: Authorization code & code verifier (4)
Note right of Identity Provider: Validate authorization code &<br/>code_verifier
Identity Provider->>App: Access token and ID token (4)
deactivate App
App->>Your API: Request protected data with access token (5)
```

1. The user clicks sign-in within the application.
2. `signinRedirect()` or `signinPopup()` must be used to start the flow.
3. The identity provider authenticates the user and stores the code_challenge and redirects the user back to the application with an authorization code.
4. `signinCallback()` handles this callback by sending this authorization code and code_verifier to the identity provider and receiving in return the access token and ID token.
5. The access token is now accessible via `getUser()?.access_token` and inserted into the requests to your protected API.
46 changes: 46 additions & 0 deletions docs/protocols/authorization-code-grant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Authorization Code Grant

The authorization code protocol is part of OAuth 2.0 defined in ([OAuth 2.0 RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)). It involves the exchange of an authorization code for a token.

**NOTE**<br/>
It implies some security risks, so you should only use it after a security assessment.


## Security concerns
This flow can only be used for applications, which can protected the client secret:
- **Native app**: Can not securely store the client secret, as its possible to decompile the application.
- **Single-page app**: Can not securely store the client secret, as the full code is exposed in the users browser

In that scenarios [Authorization Code Grant with Proof Key for Code Exchange (PKCE)](authorization-code-flow-with-pkce.md) must be used.


## Principle of function
```mermaid
---
title: Authorization Code Grant
---
sequenceDiagram
actor User
User->>App: Click sign-in link (1)
activate App
App->>Identity Provider: Authorization code request (2)
deactivate App
Identity Provider-->>User: Redirect to login/authorization prompt (3)
User-->>Identity Provider: Authenticate (3)
Identity Provider->>App: Authorization code (3)
activate App
App->>Identity Provider: Authorization code & client secret (4)
Note right of Identity Provider: Validate authorization code &<br/>client secret
Identity Provider->>App: Access token and ID token (4)
deactivate App
App->>Your API: Request protected data with access token (5)
```

1. The user clicks sign-in within the application.
2. `signinRedirect()` or `signinPopup()` must be used to start the flow.
3. The identity provider authenticates the user and stores the code_challenge and redirects the user back to the application with an authorization code.
4. `signinCallback()` handles this callback by sending this authorization code and client secret to the identity provider and receiving in return the access token and ID token.
5. The access token is now accessible via `getUser()?.access_token` and inserted into the requests to your protected API.
23 changes: 23 additions & 0 deletions docs/protocols/refresh-token-grant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Refresh Token Grant

This protocol is part of OAuth 2.0 (defined in [OAuth 2.0 RFC 6749, section 1.5](https://tools.ietf.org/html/rfc6749#section-1.5)).
The refresh token grant is used by clients to exchange a refresh token for an access token when the access token has expired.


## Principle of function
```mermaid
---
title: Refresh Token Grant
---
sequenceDiagram
App->>Identity Provider: Request new access token with refresh token (1)
activate App
Note right of Identity Provider: Validate refresh token
Identity Provider->>App: Access token and optional refresh token (1)
deactivate App
App->>Your API: Request protected data with refreshed access token (2)
```

1. `signinSilent()` must be used to start the flow.
2. The refreshed access token is now accessible via `getUser()?.access_token` and inserted into the requests to your protected API.
39 changes: 34 additions & 5 deletions docs/ropc.md → ...ource-owner-password-credentials-grant.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
## Security concerns on Resource Owner Password Credentials flow
# Resource Owner Password Credentials (ROPC) Grant

This OAuth 2.0 flow implies some security risks, so you should only use it after a security assesment.
This protocol is part of OAuth 2.0 (defined in [OAuth 2.0 RFC 6749, section 4.3](https://www.rfc-editor.org/rfc/rfc6749#section-4.3)).

To start with, this flow is not part of the [Open ID Connect standard](https://openid.net/specs/openid-connect-core-1_0.html). Furthermore, although it is part of [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc6749#section-4.3), it has been removed in the [OAuth 2.1 draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-10), and there are good reasons for this:
**NOTE**<br/>
It implies some security risks, so you should only use it after a security assessment.


## Security concerns

To start with, this flow is not part of the [Open ID Connect standard](https://openid.net/specs/openid-connect-core-1_0.html). Furthermore, although it is part of OAuth 2.0, it has been removed in the [OAuth 2.1 draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-10), and there are good reasons for this:

* When using this flow, the credentials of the user are exposed to the client application. The RFC mandates that ["the client application MUST discard the credentials once the access token has been obtained"](https://www.rfc-editor.org/rfc/rfc6749#section-4.3.1), but there is no technical way for the Identity Provider / Authorization Server to enforce this point. This flow MUST NOT be allowed unless the Client can be enforced to fulfill this requirement through other means (probably because both are under the same security domain, probably the same organization or similar constraints). This point is covered [several](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3) [times](https://www.rfc-editor.org/rfc/rfc6749#section-4.3) during the RFC and by some IdP implementations, such as [Auth0](https://auth0.com/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow) or [Keycloak](https://www.keycloak.org/docs/latest/securing_apps/#_resource_owner_password_credentials_flow), but it is sometimes quickly ignored by some developers.

* Even if the previous point is covered, this flow is increasing the attack surface of the system. For example, if the Client Application is compromised (maybe through an XSS attack, for example), the credentials of the user are exposed, so the attacker have access to other applications accessible by the user. In comparison, for example, in the Authorization Code Flow if the Client Application is equaly compromised only the access token is exposed, usually meaning that only the given application has been compromised. A different way to see this is: usually the IdP/Authorization Server are strongly protected, and the Client Applications are allowed lower levels of security auditing... but when using this flow, if any of them is exposed, the user credentials are exposed; so both of them should be equaly treated regarding security.
* Even if the previous point is covered, this flow is increasing the attack surface of the system. For example, if the Client Application is compromised (maybe through an XSS attack, for example), the credentials of the user are exposed, so the attacker have access to other applications accessible by the user. In comparison, for example, in the Authorization Code Flow if the Client Application is equally compromised only the access token is exposed, usually meaning that only the given application has been compromised. A different way to see this is: usually the IdP/Authorization Server are strongly protected, and the Client Applications are allowed lower levels of security auditing... but when using this flow, if any of them is exposed, the user credentials are exposed; so both of them should be equally treated regarding security.

Therefor, this flow MUST NOT be used as a replacement for the Authorization Code flow. This flow can only be seen as a replacement of classic form-based user/password authentication directly in the application.

Then, why are we adding this support in `oidc-client-ts`? Well... form-based user/password authentication is actually widely used in the industry, and using a standard IdP as authenticator for this architecture has some benefits (other things, such as password expiration, user management backoffice, etc are provided for free by the IdP). So this flow can be an easy help in this scenario. But you MUST NOT use this flow believing that you are having all the security benefits of OpenId Connect or OAuth; you are not.
Then, why are we adding this support in `oidc-client-ts`? Well... form-based user/password authentication is actually widely used in the industry, and using a standard IdP as authenticator for this architecture has some benefits (other things, such as password expiration, user management back-office, etc are provided for free by the IdP). So this flow can be an easy help in this scenario. But you MUST NOT use this flow believing that you are having all the security benefits of OpenId Connect or OAuth; you are not.


## Principle of function
```mermaid
---
title: Resource Owner Password Credentials (ROPC) Grant
---
sequenceDiagram
actor User
User->>App: Click sign-in link (1)
activate App
App->>Identity Provider: Authenticate with username and password (2)
Note right of Identity Provider: Validate username &<br/>password
Identity Provider->>App: Access token and ID token (2)
deactivate App
App->>Your API: Request protected data with access token (3)
```

1. The user clicks sign-in within the application.
2. `signinResourceOwnerCredentials()` must be used to start the flow.
3. The access token is now accessible via `getUser()?.access_token` and inserted into the requests to your protected API.
Loading

0 comments on commit cb52133

Please sign in to comment.