# Sign in customers

Pliro supports signing customers into your website using [the OpenID Connect Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth):

{% @mermaid/diagram content="sequenceDiagram
Customer->>Your website: Clicks the sign in button
Your website->>Your website: Generates authorization URI including a redirect URI
Your website-->>Customer: Redirects to Pliro's authorization endpoint
Customer->>Pliro: Requests the authorization endpoint
Pliro-->>Customer: Shows the Pliro sign in screen
Customer->>Pliro: Signs in
Pliro-->>Customer: Redirects to the provided redirect URI
Customer->>Your website: Requests the redirect URI
Your website->>Pliro: Requests access and ID tokens
Pliro-->>Your website: Responds with access and ID tokens
Your website->>Your website: Signs customer in and stores tokens
Your website-->>Customer: Welcomes signed in customer" %}

Here's how it works step-by-step:

## Step 1: Request an authorization code

When the customer clicks the sign in button on your website you'll need to redirect them to Pliro's authorization endpoint:

```
HTTP/1.1 302 Found
Location: https://example-publication.plirotest.page/oauth/authorize?
  response_type=code&
  scope=openid%20email%20profile&
  client_id=example-client-id&
  redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
```

This endpoint requires the following query parameters:

* `response_type`: Must be set to `code`.
* `scope`: A space-separated list of requested scopes. Must include `openid`. Can optionally include `email` to request that the customer's email is included in ID tokens, and `profile` to request the inclusion of the customer's name and subscription plan. Example: `openid email profile`.
* `client_id`: Must be set to the client ID shown for your OAuth application in the Pliro dashboard.
* `redirect_uri`: Must be set to the redirect URI you have specified for your OAuth application in the Pliro dashboard. The provided URI can optionally include query parameters not included in the registered redirect URI.

After you have redirected the customer to this endpoint, Pliro will prompt the customer to sign in. When the customer has signed in, Pliro will redirect them to the provided `redirect_uri` with an authorization code in the `code` query parameter. For example:

```
HTTP/1.1 302 Found
Location: https://example.com/callback?code=example-code
```

The authorization endpoint also accepts the following optional parameters:

* `state`: Recommended. If set, a `state` query parameter with the same value will be added to the `redirect_uri` before redirecting the customer back to your website. We recommend storing this value in the customer's session in a way that can't be tampered with before redirecting them to Pliro, and then checking that the `state` parameter in the request to the redirect URI matches the one stored in the session. This provides [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) protection.
* `prompt`: When set to `none`, Pliro won't prompt the customer to sign in. See the section [Silent re-authentication](#silent-re-authentication) below for more information on this.

### Error handling

If the authorization request fails due to an invalid `redirect_uri` or `client_id`, the customer will not be redirected to the `redirect_uri`.

In case of other errors, the customer will be redirected to the `redirect_ur` with an error code in the `error` query parameter. For example:

```
HTTP/1.1 302 Found
Location: https://example.com/callback?error=invalid_request
```

Pliro can return the following error codes:

* `invalid_request`: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
* `unauthorized_client`: The client is not authorized to request an authorization code using this method.
* `unsupported_response_type`: The server does not support obtaining an authorization code using this method.
* `invalid_scope`: The requested scope is invalid, unknown, or malformed.
* `server_error`: The server encountered an unexpected condition that prevented it from fulfilling the request.
* `login_required`: The customer needs to sign in. This error is returned when the `prompt` parameter is set to `none` and the customer is currently signed out of Pliro.

## Step 2: Request access and ID tokens

When your website processes the request to the `redirect_uri` (and has verified its authenticity using the `state` parameter), it can exchange the `code` for access and ID tokens by making a request to the token endpoint:

```
POST /oauth/token HTTP/1.1
Host: example-publication.plirotest.page
Content-Type: application/x-www-form-urlencoded
Authorization: Basic WU9VUl9DTElFTlRfSUQ6WU9VUl9DTElFTlRfU0VDUkVU

grant_type=authorization_code&
code=example-code&
redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
```

The request needs to include [Basic authentication](https://datatracker.ietf.org/doc/html/rfc7617) using your application's client ID as the username and client secret as the password.

The successful response includes access and ID tokens:

```
HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "example-access-token",
  "token_type": "Bearer",
  "expires_in":7200,
  "scope": "openid email profile",
  "created_at": 1679395531,
  "id_token": "example-id-token"
}
```

### Error handling

If the token request fails, the server responds with an HTTP 400 or 401 status code and includes an error code in the response body:

```
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
 "error": "invalid_request"
}
```

* `invalid_request`: The request is missing a required parameter, includes an unsupported parameter value (other than grant type), repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.
* `invalid_client`: Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).
* `invalid_grant`: The provided authorization grant (e.g., authorization code) is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
* `unauthorized_client`: The authenticated client is not authorized to use this authorization grant type.
* `unsupported_grant_type`: The authorization grant type is not supported by the authorization server.

## Step 3: Sign the customer in and store their tokens

You can now sign the customer into your website (e.g., by setting a session cookie). You should also store the following information in their session:

* Their access token: This is required to [retrieve updated customer information](#retrieve-updated-customer-information).
* Their id token: This is required to [sign customers out of Pliro](#sign-customers-out-of-pliro).

The ID token contains additional information, in the form of a [JSON Web Token](https://www.rfc-editor.org/rfc/rfc7519), that you may want to store separately:

* The customer's Pliro session ID (`sid`): This can be useful when [processing sign-out notifications](https://docs.pliro.co/connect/sign-out-notifications).
* The customer's email (if the `email` scope was included in the authorization request).
* The customer's name (if the `profile` scope was included in the authorization request).
* The slug for the plan that the customer subscribes to (if the `profile` scope was included in the authorization request). This can be useful when managing the customer's access to protected content.

To access this information, the ID token needs to be decoded. This can be done with one of [the many existing JWT libraries](https://jwt.io/libraries). Use [Pliro's signing keys](https://docs.pliro.co/connect/signing-keys) when verifying the token's signature.

## Step 4: Grant the customer access to protected content

Whenever the customer attempts to access a protected piece of content you can use the information stored in their session to authorize their access. At some point you may want to [update this information](https://docs.pliro.co/connect/update-customer-information).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pliro.co/connect/sign-in-customers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
