# Patron Authentication

Provider API v0.6.7 · 6 operasjoner
Kilde: https://plasapi.com/no/provider/v0.6.7/patron-authentication/

Logging a patron in and getting their patron ID, either with an identifier and a credential, with an identifier alone where the provider allows it, or through an identity provider. Also changing a credential the patron knows, and resetting one they have forgotten.

## Change the patron's own password or pin code.

`POST` `/patron/{patronId}/credential/change` · `ChangePatronCredential`

Change a credential the patron already knows.

The `credential` field says which credential is being changed, and the current and new values are named after it, so a password and a pin code can never be sent in each other's place. It must be one of the credentials in patron->credentials->changeable in the configuration, otherwise the provider returns the error code 100013.

The provider must verify the current credential before applying the new one, and returns the error code 100001 if it is wrong. This is the only proof in the request that the caller is the patron, since the bearer token identifies the vendor and `patronId` is just an identifier.

PLAS states no format for a password or a pin code. If the provider rejects the new value it returns the error code 100011, and the info should say what was wrong, since there is nothing in the configuration for the vendor to validate against beforehand.

The endpoint is also a way to guess the current credential, so the provider is expected to rate limit it per patron, and should answer 429 rather than 400 once the limit is reached. This matters most for a pin code, which is short enough to be guessed outright if nothing throttles the attempts.

A patron who does not know their current credential uses POST /patron/credential/reset instead.


### Eksempel på kall

**cURL**

```bash
curl -X POST "$PLAS_BASE_URL/patron/40218873/credential/change?version=0.6.7" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $PLAS_TOKEN" \
  -d '{
  "credential": "password",
  "currentPassword": "correct-horse-battery",
  "newPassword": "lantern-river-staple"
}'
```

**JavaScript**

```javascript
const response = await fetch(`${process.env.PLAS_BASE_URL}/patron/40218873/credential/change?version=0.6.7`, {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.PLAS_TOKEN}`,
  },
  body: JSON.stringify({
    "credential": "password",
    "currentPassword": "correct-horse-battery",
    "newPassword": "lantern-river-staple"
  }),
});
```

**Python**

```python
import os
import requests

response = requests.post(
    f"{os.environ['PLAS_BASE_URL']}/patron/40218873/credential/change",
    params={
        "version": "0.6.7",
    },
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": f"Bearer {os.environ['PLAS_TOKEN']}",
    },
    json={
        "credential": "password",
        "currentPassword": "correct-horse-battery",
        "newPassword": "lantern-river-staple",
    },
)
response.raise_for_status()
```

Verten og tokenet er miljøvariabler: `PLAS_BASE_URL` providerens adresse · `PLAS_TOKEN` et access token.

### Parametere

- `patronId` (i `path`, `string`, påkrevd) — Patron ID from authentication.

Felles for operasjonene: `version`. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

### Request body

`application/json` · påkrevd

[`ChangePatronCredentialRequestBody`](https://plasapi.com/no/provider/v0.6.7/schemas/#ChangePatronCredentialRequestBody)

### Svar

#### `204` The credential was changed, and the current value no longer works.

Ikke noe innhold i svaret.

#### `400` The list of errors.

`Errors`

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

Eksempel (Generert fra skjemaet):

```json
{
  "errors": [
    {
      "code": 200103,
      "info": "200103: invalid/unsupported query parameter value"
    }
  ]
}
```

#### `401` Bearer token invalid, missing, or expired.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

#### `404` Resource not found.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

#### `429` Too many requests. The provider is rate limiting and did not carry out the request.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

## Authenticate patron

`POST` `/patron/authentication` · `AuthenticatePatron`

Authenticate patron by credentials.

### Eksempel på kall

**cURL**

```bash
curl -X POST "$PLAS_BASE_URL/patron/authentication?version=0.6.7" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $PLAS_TOKEN" \
  -d '{
  "identifier": {
    "type": "local",
    "value": "N00012345"
  },
  "password": "correct-horse-battery"
}'
```

**JavaScript**

```javascript
const response = await fetch(`${process.env.PLAS_BASE_URL}/patron/authentication?version=0.6.7`, {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.PLAS_TOKEN}`,
  },
  body: JSON.stringify({
    "identifier": {
      "type": "local",
      "value": "N00012345"
    },
    "password": "correct-horse-battery"
  }),
});
const data = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    f"{os.environ['PLAS_BASE_URL']}/patron/authentication",
    params={
        "version": "0.6.7",
    },
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": f"Bearer {os.environ['PLAS_TOKEN']}",
    },
    json={
        "identifier": {
            "type": "local",
            "value": "N00012345",
        },
        "password": "correct-horse-battery",
    },
)
data = response.json()
```

Verten og tokenet er miljøvariabler: `PLAS_BASE_URL` providerens adresse · `PLAS_TOKEN` et access token.

### Parametere

Felles for operasjonene: `version`. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

### Request body

`application/json` · påkrevd

Authentication Patron

[`PatronAuthenticationRequestBody`](https://plasapi.com/no/provider/v0.6.7/schemas/#PatronAuthenticationRequestBody)

### Svar

#### `200` Success

`PatronAuthenticationResponseBody`

Eksempel (Generert fra skjemaet):

```json
{
  "patron": {
    "address": {
      "city": "Nordby",
      "country": "Norway",
      "postalCode": "0182",
      "street": "Storgata 12"
    },
    "emails": [
      {
        "default": true,
        "email": "kari.nordmann@example.no",
        "verified": "yes"
      }
    ],
    "fullName": "Kari Nordmann",
    "givenName": "Kari",
    "identifiers": [
      {
        "type": "local",
        "value": "N00012345"
      }
    ],
    "patronId": "40218873",
    "permissions": [
      {
        "reason": "The patron has unpaid fees above the library’s limit.",
        "status": "allowed",
        "type": "off_hours"
      }
    ],
    "phoneNumbers": [
      {
        "default": true,
        "number": "+4791234567",
        "type": "mobile",
        "verified": "yes"
      }
    ],
    "pickupLocation": {
      "branchId": "nordby-main",
      "branchName": "Nordby Main Library",
      "sections": [
        {
          "id": "nordby-main-children",
          "name": "Children’s department",
          "type": "department"
        }
      ]
    },
    "reservation": {
      "postpone": {
        "fromDate": "2025-03-01",
        "toDate": "2025-03-31"
      }
    },
    "surname": "Nordmann"
  }
}
```

#### `400` The list of errors.

`Errors`

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

Eksempel (Generert fra skjemaet):

```json
{
  "errors": [
    {
      "code": 200103,
      "info": "200103: invalid/unsupported query parameter value"
    }
  ]
}
```

#### `401` Bearer token invalid, missing, or expired.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

## This will fetch a SSO URL used for patron login, matching the chosen identity provider.

`GET` `/patron/authentication/identity-provider` · `GetPatronAuthenticationUrl`

### Eksempel på kall

**cURL**

```bash
curl -X GET "$PLAS_BASE_URL/patron/authentication/identity-provider?identity_provider=norway_id_portal&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&state=af0ifjsldkj&version=0.6.7" \
  -H 'Accept: application/json' \
  -H "Authorization: Bearer $PLAS_TOKEN"
```

**JavaScript**

```javascript
const response = await fetch(`${process.env.PLAS_BASE_URL}/patron/authentication/identity-provider?identity_provider=norway_id_portal&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&state=af0ifjsldkj&version=0.6.7`, {
  method: "GET",
  headers: {
    "Accept": "application/json",
    "Authorization": `Bearer ${process.env.PLAS_TOKEN}`,
  },
});
const data = await response.json();
```

**Python**

```python
import os
import requests

response = requests.get(
    f"{os.environ['PLAS_BASE_URL']}/patron/authentication/identity-provider",
    params={
        "identity_provider": "norway_id_portal",
        "code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
        "state": "af0ifjsldkj",
        "version": "0.6.7",
    },
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {os.environ['PLAS_TOKEN']}",
    },
)
data = response.json()
```

Verten og tokenet er miljøvariabler: `PLAS_BASE_URL` providerens adresse · `PLAS_TOKEN` et access token.

### Parametere

- `identity_provider` (i `query`, [`ConfigurationPatronIdentityProviderType`](https://plasapi.com/no/provider/v0.6.7/schemas/#ConfigurationPatronIdentityProviderType), påkrevd) — The identity provider type, found in GET /configuration.
- `code_challenge` (i `query`, `string`, påkrevd) — A hashed value (of the code_verifier from a PKCE flow) used to secure the authorization code exchange.
- `state` (i `query`, `string`, påkrevd) — A random string to protect against CSRF and track the request state. The value should be returned to the Vendor on the callback url after login.
- `prompt` (i `query`, `string enum`, valgfri) — If prompt is set to login, the returned url should force a new login, even if the user is already logged in.
- `app_redirect_url` (i `query`, `string (uri)`, valgfri) — This value should be returned to the Vendor on the callback url after login.

Felles for operasjonene: `version`. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

### Svar

#### `200` Success

`PatronAuthenticationIdentityProviderResponseBody`

Eksempel (Generert fra skjemaet):

```json
{
  "url": "https://nordby.bibliotek.example/url"
}
```

#### `400` The list of errors.

`Errors`

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

Eksempel (Generert fra skjemaet):

```json
{
  "errors": [
    {
      "code": 200103,
      "info": "200103: invalid/unsupported query parameter value"
    }
  ]
}
```

#### `401` Bearer token invalid, missing, or expired.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

## Authenticate patron by code and code verifier from SSO login.

`POST` `/patron/authentication/identity-provider` · `AuthenticatePatronByCodeAndCodeVerifier`

### Eksempel på kall

**cURL**

```bash
curl -X POST "$PLAS_BASE_URL/patron/authentication/identity-provider?version=0.6.7" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H "Authorization: Bearer $PLAS_TOKEN" \
  --data-urlencode 'code=SplxlOBeZQQYbYS6WxSbIA' \
  --data-urlencode 'code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk' \
  --data-urlencode 'identity_provider=norway_id_portal'
```

**JavaScript**

```javascript
const response = await fetch(`${process.env.PLAS_BASE_URL}/patron/authentication/identity-provider?version=0.6.7`, {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": `Bearer ${process.env.PLAS_TOKEN}`,
  },
  body: new URLSearchParams({
    "code": "SplxlOBeZQQYbYS6WxSbIA",
    "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
    "identity_provider": "norway_id_portal",
  }),
});
const data = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    f"{os.environ['PLAS_BASE_URL']}/patron/authentication/identity-provider",
    params={
        "version": "0.6.7",
    },
    headers={
        "Accept": "application/json",
        "Content-Type": "application/x-www-form-urlencoded",
        "Authorization": f"Bearer {os.environ['PLAS_TOKEN']}",
    },
    data={
        "code": "SplxlOBeZQQYbYS6WxSbIA",
        "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
        "identity_provider": "norway_id_portal",
    },
)
data = response.json()
```

Verten og tokenet er miljøvariabler: `PLAS_BASE_URL` providerens adresse · `PLAS_TOKEN` et access token.

### Parametere

Felles for operasjonene: `version`. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

### Request body

`application/x-www-form-urlencoded` · påkrevd

[`PatronAuthenticationByCodeAndCodeVerifierRequestBody`](https://plasapi.com/no/provider/v0.6.7/schemas/#PatronAuthenticationByCodeAndCodeVerifierRequestBody)

### Svar

#### `200` Success

`PatronAuthenticationByCodeAndCodeVerifierResponseBody`

Eksempel (Generert fra skjemaet):

```json
{
  "patron": {
    "address": {
      "city": "Nordby",
      "country": "Norway",
      "postalCode": "0182",
      "street": "Storgata 12"
    },
    "emails": [
      {
        "default": true,
        "email": "kari.nordmann@example.no",
        "verified": "yes"
      }
    ],
    "fullName": "Kari Nordmann",
    "givenName": "Kari",
    "identifiers": [
      {
        "type": "local",
        "value": "N00012345"
      }
    ],
    "patronId": "40218873",
    "permissions": [
      {
        "reason": "The patron has unpaid fees above the library’s limit.",
        "status": "allowed",
        "type": "off_hours"
      }
    ],
    "phoneNumbers": [
      {
        "default": true,
        "number": "+4791234567",
        "type": "mobile",
        "verified": "yes"
      }
    ],
    "pickupLocation": {
      "branchId": "nordby-main",
      "branchName": "Nordby Main Library",
      "sections": [
        {
          "id": "nordby-main-children",
          "name": "Children’s department",
          "type": "department"
        }
      ]
    },
    "reservation": {
      "postpone": {
        "fromDate": "2025-03-01",
        "toDate": "2025-03-31"
      }
    },
    "surname": "Nordmann"
  }
}
```

#### `400` The list of errors.

`Errors`

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

Eksempel (Generert fra skjemaet):

```json
{
  "errors": [
    {
      "code": 200103,
      "info": "200103: invalid/unsupported query parameter value"
    }
  ]
}
```

#### `401` Bearer token invalid, missing, or expired.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

## Authenticate patron without use of a password

`POST` `/patron/authentication/no-password` · `AuthenticatePatronNoPassword`

Authenticate patron without use of a password. This should only be used when absolutely necessary.

### Eksempel på kall

**cURL**

```bash
curl -X POST "$PLAS_BASE_URL/patron/authentication/no-password?version=0.6.7" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $PLAS_TOKEN" \
  -d '{
  "identifier": {
    "type": "local",
    "value": "N00012345"
  }
}'
```

**JavaScript**

```javascript
const response = await fetch(`${process.env.PLAS_BASE_URL}/patron/authentication/no-password?version=0.6.7`, {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.PLAS_TOKEN}`,
  },
  body: JSON.stringify({
    "identifier": {
      "type": "local",
      "value": "N00012345"
    }
  }),
});
const data = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    f"{os.environ['PLAS_BASE_URL']}/patron/authentication/no-password",
    params={
        "version": "0.6.7",
    },
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": f"Bearer {os.environ['PLAS_TOKEN']}",
    },
    json={
        "identifier": {
            "type": "local",
            "value": "N00012345",
        },
    },
)
data = response.json()
```

Verten og tokenet er miljøvariabler: `PLAS_BASE_URL` providerens adresse · `PLAS_TOKEN` et access token.

### Parametere

Felles for operasjonene: `version`. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

### Request body

`application/json` · påkrevd

Authentication Patron without using password

[`PatronAuthenticationNoPasswordRequestBody`](https://plasapi.com/no/provider/v0.6.7/schemas/#PatronAuthenticationNoPasswordRequestBody)

### Svar

#### `200` Success

`PatronAuthenticationNoPasswordResponseBody`

Eksempel (Generert fra skjemaet):

```json
{
  "patron": {
    "address": {
      "city": "Nordby",
      "country": "Norway",
      "postalCode": "0182",
      "street": "Storgata 12"
    },
    "emails": [
      {
        "default": true,
        "email": "kari.nordmann@example.no",
        "verified": "yes"
      }
    ],
    "fullName": "Kari Nordmann",
    "givenName": "Kari",
    "identifiers": [
      {
        "type": "local",
        "value": "N00012345"
      }
    ],
    "patronId": "40218873",
    "permissions": [
      {
        "reason": "The patron has unpaid fees above the library’s limit.",
        "status": "allowed",
        "type": "off_hours"
      }
    ],
    "phoneNumbers": [
      {
        "default": true,
        "number": "+4791234567",
        "type": "mobile",
        "verified": "yes"
      }
    ],
    "pickupLocation": {
      "branchId": "nordby-main",
      "branchName": "Nordby Main Library",
      "sections": [
        {
          "id": "nordby-main-children",
          "name": "Children’s department",
          "type": "department"
        }
      ]
    },
    "reservation": {
      "postpone": {
        "fromDate": "2025-03-01",
        "toDate": "2025-03-31"
      }
    },
    "surname": "Nordmann"
  }
}
```

#### `400` The list of errors.

`Errors`

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

Eksempel (Generert fra skjemaet):

```json
{
  "errors": [
    {
      "code": 200103,
      "info": "200103: invalid/unsupported query parameter value"
    }
  ]
}
```

#### `401` Bearer token invalid, missing, or expired.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

## Request that a reset link is sent to the patron.

`POST` `/patron/credential/reset` · `ResetPatronCredential`

Request that the provider sends a link, so the patron can set a credential they no longer know.

The identifier follows patron->login->identifierTypes in the configuration, since this is the recovery path for login.

The `credential` field says which credential to reset, and must be one of the credentials in patron->credentials->resettable in the configuration. If the field is missing, the provider decides which credential to reset.

The email in the request selects which of the patron's registered addresses to use, and is never a destination in its own right.  
The link is only sent if that address is already attached to the identified patron and verified there. An attached but unverified address is treated exactly like no match, since the vendor can write patron email addresses through PATCH /patron/{patronId}/information.

If no link is sent, for any reason including rate limiting, the response is still 202. The endpoint must not reveal whether a patron exists, or which email addresses are attached to one, so neither the response nor the time it takes should differ between a match and no match.

The 400 is only for a malformed request body. In particular the error codes 100023 and 100013 must not be returned.

The link is the provider's, but the token in it must be unguessable, must be single use, and must expire after a short period. The request deliberately carries no URL, so the link cannot be pointed at a host chosen by the caller.


### Eksempel på kall

**cURL**

```bash
curl -X POST "$PLAS_BASE_URL/patron/credential/reset?version=0.6.7" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $PLAS_TOKEN" \
  -d '{
  "credential": "password",
  "email": "kari.nordmann@example.no",
  "identifier": {
    "type": "local",
    "value": "N00012345"
  }
}'
```

**JavaScript**

```javascript
const response = await fetch(`${process.env.PLAS_BASE_URL}/patron/credential/reset?version=0.6.7`, {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.PLAS_TOKEN}`,
  },
  body: JSON.stringify({
    "credential": "password",
    "email": "kari.nordmann@example.no",
    "identifier": {
      "type": "local",
      "value": "N00012345"
    }
  }),
});
```

**Python**

```python
import os
import requests

response = requests.post(
    f"{os.environ['PLAS_BASE_URL']}/patron/credential/reset",
    params={
        "version": "0.6.7",
    },
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": f"Bearer {os.environ['PLAS_TOKEN']}",
    },
    json={
        "credential": "password",
        "email": "kari.nordmann@example.no",
        "identifier": {
            "type": "local",
            "value": "N00012345",
        },
    },
)
response.raise_for_status()
```

Verten og tokenet er miljøvariabler: `PLAS_BASE_URL` providerens adresse · `PLAS_TOKEN` et access token.

### Parametere

Felles for operasjonene: `version`. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

### Request body

`application/json` · påkrevd

[`ResetPatronCredentialRequestBody`](https://plasapi.com/no/provider/v0.6.7/schemas/#ResetPatronCredentialRequestBody)

### Svar

#### `202` The request was accepted. Whether a link is sent is decided after this response, so this is also the response when no link will be sent at all.

Ikke noe innhold i svaret.

#### `400` The list of errors.

`Errors`

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)

Eksempel (Generert fra skjemaet):

```json
{
  "errors": [
    {
      "code": 200103,
      "info": "200103: invalid/unsupported query parameter value"
    }
  ]
}
```

#### `401` Bearer token invalid, missing, or expired.

Ikke noe innhold i svaret.

Felles svar, definert én gang for hele API-et. [Se den felles kontrakten på versjonssiden.](https://plasapi.com/no/provider/v0.6.7/)
