arrow-left
Only this pageAll pages
gitbookPowered by GitBook
1 of 42

Authority

Loading...

Loading...

Loading...

Loading...

Getting Started

Loading...

Loading...

Loading...

Authentication

Loading...

Loading...

Loading...

Security & Error Handling

Loading...

Loading...

Providers

Loading...

Loading...

API Endpoints

Loading...

DEVELOPMENT

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Reference

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Authentication Guide

Authority provides a simple yet flexible authentication system using OAuth.

hashtag
Setting up OAuth

  1. Register your application with the desired OAuth provider.

  2. Obtain the client ID and client secret.

  3. Set these in the environment variables OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET.

hashtag
OAuth Flow

  • Users will be redirected to the OAuth provider for authentication.

  • Once authenticated, the provider will return an authorization code.

  • This code can be exchanged for an access token, which can be used for further API requests.

Client Providers

hashtag
Overview

Client providers are responsible for managing OAuth clients in the Authority authentication system. They represent applications that request access to user resources on behalf of the users.

hashtag
Configuring Client Providers

To set up a client provider, you'll need to configure Authly config/authly.cr settings for your application. This is typically done by defining a Client Provider class that has access to the registered client data.

hashtag
Create a class similar to the example below

Example:

hashtag
Register the class in config/authly.cr

hashtag
Example

hashtag
Using Client Providers

Once configured, your application can initiate the OAuth flow by redirecting users to the provider's authorization page. Here's an example of how the flow works:

  1. The user is redirected to the OAuth provider.

  2. After authentication, the user is redirected back to your application with an authorization code.

  3. Use this code to request an access token.

In your CLIENT application, you must use the client_id and client_secret generated by the provider

Client providers allow your application to securely interact with OAuth providers on behalf of users.

circle-info

Performing HTTP client requests with OAuth2 authentication

https://crystal-lang.org/api/1.13.3/OAuth2.htmlarrow-up-right
module Authority
  class ClientProvider
    include Authly::AuthorizableClient

    def valid_redirect?(client_id : String, redirect_uri : String) : Bool
      ClientRepo.valid_redirect?(client_id, redirect_uri)
    end

    def authorized?(client_id : String, client_secret : String) : Bool
      ClientRepo.authorized?(client_id, client_secret)
    end
  end
end
require "authly"

# Configure
Authly.configure do |c|
  ...
 
  c.clients = Authority::ClientProvider.new
end
OAuth::Client.new do |client|
  client.client_id = ENV["CLIENT_ID"]
  client.client_secret = ENV["CLIENT_SECRET"]
end

OAuth 2 Grant Flows

A grant is a method of acquiring an access token. Deciding which grants to implement depends on the type of client the end-user will be using, and the experience you want for your users.

Dive into the specifics of each OAuth 2 Flow implementation

Device Flowchevron-rightAuthorization Flowchevron-rightLegacy: Implicit grantchevron-rightClient Credentials Flowchevron-rightLegacy: Passwordchevron-rightRefreshing Access Tokenschevron-rightAccess Token Responsechevron-right

Introduction

A OAuth2 Server, sometimes also referred to as an OAuth 2.0 Server, OAuth Server, Authorization Server, is a software system that implements network protocol flows that allow a client software applica

hashtag
About Authority Server

Authority is an OAuth 2 Server, sometimes also referred to as an OAuth 2.0 Server, OAuth Server, Authorization Server, is a software system that implements network protocol flows that allow a client software application to act on behalf of a user.

Authority is an OpenID OAuth 2.0 Server and OpenID Connect Provider written in Crystal optimized for low-latency, high throughput, and low resource consumption. Authority has a built in identity provider user login.

Authority is an open source API security for your infrastructure.

hashtag
Architecture

Authority follows architecture principles that work best on container orchestration systems such as Kubernetes, CloudFoundry, OpenShift, and similar projects. While it is possible to run the Authority stack on a RaspberryPI, the integration with the Docker and Container ecosystem is best documented and supported.

Authority's architecture is designed along several guiding principles:

  • Minimal dependencies (no system dependencies; might need a database backend)

  • Runs everywhere (Linux, macOS, FreeBSD, Windows; AMD64, i386, ARMv5, ...)

  • Scales without effort (no memcached, etcd, required, ...)

  • Minimize room for human and network errors

hashtag
OAuth 2 Implementations

Implementing and using OAuth2 without understanding the whole specification is challenging and prone to errors, even when SDKs are being used. The primary goal of Authority is to make OAuth 2.0 and OpenID Connect 1.0 better accessible.

The Authority implements five grants for acquiring an access token:

  • Authorization code Grant

  • Implicit Grant

  • Resource owner credentials grant

  • Client credentials grant

hashtag
Explore the implementations

The following RFCs are implemented:

hashtag
Why Authority is Different​

Authority differentiates itself in the following key areas:

  • Everything is developed and licensed under Open Source Principles, allowing you to participate, collaborate, and understand the inner workings of Authority.

  • You can bring your own UI, in the programming language of your choosing, with the user experience that you like.

  • From designing Identity Schemas, to webhooks, to advanced configuration options - Authority is fully customizable.

Refresh token Grant

  • Device Token Grant

  • Authority spans the whole authentication and authorization real with well-designed APIs:
    • Identity Management

    • Session management

    • Flows for login

    • Registration

    • Account recovery & verification

    • Mfa, and many more.

    OAuth 2 Grant Flowschevron-right
    RFC6749 "OAuth 2.0"arrow-up-right
    RFC6750 " The OAuth 2.0 Authorization Framework: Bearer Token Usage"arrow-up-right
    RFC7519 "JSON Web Token (JWT)"arrow-up-right
    RFC7636 "Proof Key for Code Exchange by OAuth Public Clients"arrow-up-right

    In Action

    hashtag
    Authorization Flow

    Customizing Authentication

    You can modify the default behavior of the Authority authentication system by extending the authentication logic.

    hashtag
    Custom OAuth Providers

    To add a custom OAuth provider, modify the OAuth::Client configuration in the src/auth.cr file:

    OAuth::Client.new do |config|
      config.client_id = ENV["CUSTOM_OAUTH_CLIENT_ID"]
      config.client_secret = ENV["CUSTOM_OAUTH_CLIENT_SECRET"]
    end

    This allows you to connect to other OAuth providers or implement custom authentication logic.

    Installation

    hashtag
    Prerequisites

    • Crystal language installed. Follow the official Crystal installation guidearrow-up-right.

    • PostgreSQL or another supported database.

    • Docker (if using Docker setup).

    hashtag
    Steps

    1. Clone the repository:

    2. Install dependencies:

    3. Set up the database:

    4. Configure environment variables in .env.local:

    Or using Docker:

    Run the application:

    crystal run src/app.cr
    git clone <repository-url>
    cd authority
    shards install
    createdb authority_db
    cp .env.example .env.local
    docker-compose up --build

    Performance at Scale

    OAuth 1.0 requires that the protected resources endpoints have access to the client credentials in order to validate the request. This breaks the typical architecture of most large providers in which a centralized authorization server is used for issuing credentials, and a separate server is used for handling API calls. Because OAuth 1.0 requires the use of the client credentials to verify the signatures, it makes this separation very hard.

    OAuth 2.0 addresses this by using the client credentials only when the application obtains authorization from the user. After the credentials are used in the authorization step, only the resulting access token is used when making API calls. This means the API servers do not need to know about the client credentials since they can validate access tokens themselves.

    Roadmap / Features

    API Documentation

    Authority exposes several API endpoints for authentication. Below are some key endpoints:

    • POST /auth/login: Authenticate a user and obtain a token.

    • GET /auth/user: Retrieve authenticated user details.

    • POST /auth/logout: Log out a user.

    Each endpoint accepts and returns JSON data. Ensure that you include the correct OAuth token in the Authorization header for protected routes.

    Configuration Overview

    The Authority project includes several important configuration files located in the src/config directory. These files define settings for key components of the application, including sessions, authentication, and the overall system behavior.

    hashtag
    Available Configuration Files

    hashtag
    1. session.cr

    The session.cr file handles session management for the application. Sessions are crucial for maintaining user state between requests, especially in authentication systems.

    Key settings:

    • Session duration: Define how long a session should remain active before expiring.

    • Storage options: Configure where session data is stored (e.g., in-memory or database-backed).

    You can adjust session behavior based on your requirements by modifying this file.

    hashtag
    2. authly.cr

    The authly.cr file is responsible for authentication-related settings. This includes OAuth configuration and other authentication logic.

    Key settings:

    • OAuth client configuration: Define client IDs, secrets, and other OAuth-specific settings.

    • Authentication flows: Customize how the system handles different types of authentication (e.g., token-based or session-based).

    hashtag
    3. clear.cr

    The clear.cr file likely manages caching and clearing of session data or other temporary data. This file ensures that outdated session data or cache entries are purged efficiently.

    Key settings:

    • Cache expiration: Define when cached data should be invalidated.

    • Manual clearing options: Set up specific points where data is cleared to optimize performance.

    hashtag
    4. authority.cr

    The authority.cr file contains the main configurations for the Authority authentication system. This file ties together various authentication and authorization components.

    Key settings:

    • General system settings: Configure global behavior for the Authority system.

    • Custom provider options: Define how different authentication providers are integrated with the system.

    hashtag
    Customizing Configuration

    To customize any of these settings, simply open the corresponding configuration file in the src/config directory and adjust the necessary parameters. Be sure to restart the application after making changes to ensure that the new configurations are applied.

    require "session"
    
    Session.configure do |c|
      c.timeout = 1.hour
      c.session_key = ENV.fetch "SESSION_KEY", "authority.sess"
      c.secret = ENV.fetch "SESSION_SECRET", "K,n:aT5CY4Trkg2JjS\e/?F[?e(Pj/n"
      c.on_started = ->(sid : String, data : Session::Databag) { Authority.log.info { "Session started - SessionID: #{sid} - Databag: #{data}" } }
      c.on_deleted = ->(sid : String, data : Session::Databag) { Authority.log.info { "Session Revoke - SessionID: #{sid} - Databag: #{data}" } }
      c.on_loaded = ->(sid : String, data : Session::Databag) { Authority.log.info { "Session Loaded - SessionID: #{sid} - Databag: #{data}" } }
      c.on_client = ->(sid : String, data : Session::Databag) { Authority.log.info { "Session Client - SessionID: #{sid} - Databag: #{data}" } }
    end
    require "authly"
    
    # Configure
    Authly.configure do |c|
      c.secret_key = ENV.fetch "SECRET_KEY"
      c.refresh_ttl = ENV.fetch("REFRESH_TTL").try &.to_i.minutes
      c.code_ttl = ENV.fetch("CODE_TTL").try &.to_i.minutes
      c.access_ttl = ENV.fetch("ACCESS_TOKEN_TTL").try &.to_i.minutes
      c.owners = Authority::OwnerProvider.new
      c.clients = Authority::ClientProvider.new
    end
    require "clear"
    
    # Clear Orm Docs
    # https://clear.gitbook.io/project/introduction/installation
    Clear::SQL.init(ENV["DATABASE_URL"])
    require "azu"
    Log.setup_from_env
    
    module Authority
      include Azu
    
      SESSION_KEY     = ENV.fetch "SESSION_KEY", "session_id"
      BASE_URL        = ENV.fetch "BASE_URL", "http://localhost:4000"
      ACTIVATE_URL    = "#{BASE_URL}/activate"
      DEVICE_CODE_TTL = ENV.fetch("DEVICE_CODE_TTL", "300").to_i
      SESSION         = Session::CookieStore(UserSession).provider
    
      HANDLERS = [
        Azu::Handler::Rescuer.new,
        Azu::Handler::RequestID.new,
        Azu::Handler::Logger.new,
        Session::SessionHandler.new(Authority.session),
      ]
    
      def self.session
        SESSION
      end
    
      def self.current_session
        SESSION.current_session
      end
    
      configure do |c|
        c.templates.path = ENV["TEMPLATE_PATH"]
        c.router.get "/*", Handler::Static.new
      end
    end
    

    Requirements

    This project requires

    • Crystal Language - find the installation instructions here https://crystal-lang.org/install/arrow-up-right

    • Git - https://git-scm.com/book/en/v2/Getting-Started-Installing-Gitarrow-up-right

    • PostgreSQL - https://www.postgresql.org/docs/current/tutorial-install.htmlarrow-up-right

    • Docker and Docker-Compose -

    • Geckodriver - Needed for specs

    https://docs.docker.com/engine/install/arrow-up-right
    https://www.softwaretestinghelp.com/geckodriver-selenium-tutorial/arrow-up-right

    Deployment

    This tutorial walks you through a quick setup of Authority, a PostgreSQL instance, and a simple User Login & Consent App based on Docker Compose. You need to have the latest Dockerarrow-up-right and Docker Composearrow-up-right version installed.

    hashtag
    Dockerfile

    Authority project contains a simple Dockerfile that compiles and builds a simple docker image with little to no dependencies.

    FROM crystallang/crystal:latest-alpine as source
    WORKDIR /opt/app
    COPY . /opt/app
    RUN shards install
    RUN crystal build --release --static ./src/server.cr -o ./server
    CMD ["crystal", "spec"]
    
    FROM alpine:latest  
    RUN apk --no-cache add ca-certificates
    WORKDIR /root/
    COPY --from=source /opt/app/server .
    COPY --from=source /opt/app/public ./public
    CMD ["./server"]

    hashtag
    Docker-Compose

    To start using Authority run the following command

    circle-info

    To change the Authority server configuration change the local.env file

    docker-compose up server
    version: "3.7"
    services:
      db:
        image: postgres
        restart: always
        environment:
          POSTGRES_DB: authority_db
          POSTGRES_USER: auth_user
          POSTGRES_PASSWORD: auth_pass
        ports:
          - 5432:5432
    
      server:
        build:
          context: .
          dockerfile: Dockerfile
        command: ./server
        container_name: authority-server
        working_dir: /root/
        env_file:
          - local.env
        ports:
          - "4000:4000"
        depends_on:
          - db

    Error Handling & Troubleshooting

    hashtag
    Common Issues

    • Invalid OAuth Token: Ensure the token has not expired and is correctly included in the Authorization header.

    • Database Connection Failed: Check that the DATABASE_URL environment variable is set correctly.

    Check the logs for detailed error messages and follow standard Crystal debugging practices to resolve issues.

    Owner Providers

    hashtag
    Overview

    Owner providers in the Authority system represent the resource owners—typically the users who own the data or resources being accessed. They play a crucial role in controlling access to their resources.

    hashtag
    Configuring Owner Providers

    To configure an owner provider, you need to establish ownership models in your application. This usually involves mapping user records to resources that they own.

    hashtag
    Example Configuration

    In your database schema, make sure that resources have an owner_id field that corresponds to the user who owns the resource.

    hashtag
    Using Owner Providers

    Once the ownership structure is in place, you can enforce access control rules by checking whether the currently authenticated user is the owner of the resource they are trying to access.

    Example in Crystal:

    Owner providers help implement fine-grained access control mechanisms, ensuring that users can only access the resources they own.

    CREATE TABLE resources (
        id SERIAL PRIMARY KEY,
        owner_id INTEGER REFERENCES users(id)
    );
    # Model Docs - https://clear.gitbook.io/project/model/column-types
    module Authority
      class OwnerEntity
        include Clear::Model
    
        self.table = "owners"
    
        primary_key :id, type: :uuid
        column username : String
        column email : String
        column first_name : String
        column last_name : String
        column email_verified : Bool = false
        column scope : String
        column encrypted_password : Crypto::Bcrypt::Password
        timestamps
    
        def password=(plain_text : String)
          self.encrypted_password = Crypto::Bcrypt::Password.create(plain_text)
        end
    
        def verify?(password : String)
          self.encrypted_password.verify(password)
        end
    
        def id_token
          {
            "user_id"        => id.to_s,
            "first_name"     => first_name,
            "last_name"      => last_name,
            "email"          => email,
            "scope"          => scope,
            "email_verified" => email_verified.to_s,
            "created_at"     => created_at.to_s,
            "updated_at"     => updated_at.to_s,
            "iat"            => Time.utc.to_unix,
            "exp"            => 1.hour.from_now.to_unix,
          }
        end
      end
    end
    
    # Assuming `current_user` is the authenticated user and `resource` is the requested resource.
    module Authority
      class OwnerProvider
        include Authly::AuthorizableOwner
    
        def authorized?(username : String, password : String) : Bool
          OwnerRepo.authenticate? username, password
        end
    
        def id_token(user_id : String) : Hash(String, Int64 | String)
          OwnerRepo.id_token user_id
        end
      end
    end

    Database

    You can customize the database table and fields of your Authority server by simply modifying the migration files found under db/migrations.

    circle-exclamation

    A bad database configuration might stop your database from working. Take extra care to make sure the configuration is correct.

    hashtag
    Clients Migration File

    class CreateClients
      include Clear::Migration
    
      def change(direction)
        direction.up do
          create_table :clients, id: :uuid do |t|
            t.column :client_id, "uuid", index: true, unique: true, default: "uuid_generate_v4()"
            t.column :name, "varchar(120)", null: false, index: true, unique: true
            t.column :description, "varchar(2000)"
            t.column :logo, "varchar(120)", null: false
            t.column :client_secret, "varchar(80)", null: false
            t.column :redirect_uri, "varchar(2000)", null: false
            t.column :scopes, "varchar(4000)", null: false
    
            t.timestamps
          end
        end
    
        direction.down do
          execute "DROP TABLE IF EXISTS ;"
        end
      end
    end

    User Interface

    This document describes the syntax and semantics of the template engine and will be most useful as a reference to those modifying the Authority templates. As the template engine is very flexible.

    The Managed UI implements screens such as login, registration, account recovery, account setting, and account verification. This allows for fast adoption of Authority.

    Contrary to other vendors, Authority allows you to implement your own UI by offering simple HTML templates. You can change the look of Authority signin and authorize HTML pages.

    hashtag
    The Public directory

    The public directory contains all the front-end CSS and HTML-related files that compose the user interface for Authority. These are small easy to understand files that are clearly named for easy adoption.

    Just edit the ./public/templates/signin.html and ./public/templates/authorize.html

    hashtag
    HTML (jinja) Templates

    A template contains variables and/or expressions, which get replaced with values when a template is rendered; and tags, which control the logic of the template.

    Below is a minimal template that illustrates a few basics using the default Jinja configuration. We will cover the details later in this document:

    circle-info

    Learn more about the template syntax and capabilities at and

    Device Flow

    The OAuth 2.0 “Device Flow” extension enables OAuth on devices that have an Internet connection but don’t have a browser or an easy way to enter text.

    This flow is seen on devices such as smart TVs, media consoles, picture frames, printers, or hardware video encoders. In this flow, the device instructs the user to open a URL on a secondary device such as a smartphone or computer in order to complete the authorization. There is no communication channel required between the user’s two devices.

    hashtag
    Authorization Request

    First, the client makes a request to the authorization server to request the device code.

    https://jinja.palletsprojects.com/en/3.0.x/templates/arrow-up-right
    https://shards.info/github/straight-shoota/crinjaarrow-up-right
    {% extends "layout.html" %}
    {% set title = "Signin" %}
    
    {% block body %}
    <main class="login-form">
      {% include "errors.html" %}
      <form action="/signin" method="post">
        <input type="hidden" name="forward_url" id="forward_url" value="{{forward_url}}">
        <div class="avatar"><i class="material-icons">&#xE7FF;</i></div>
        <h4 class="modal-title">Login to Your Account</h4>
        <div class="form-group">
          <input type="text" class="form-control" id="username" name="username" placeholder="Username" required="required">
        </div>
        <div class="form-group">
          <input type="password" class="form-control" id="password" name="password" placeholder="Password"
            required="required">
        </div>
        <div class="form-group small clearfix">
          <label class="form-check-label"><input type="checkbox">Remember me</label>
          <a href="/forgot-password" class="forgot-link">Forgot Password?</a>
        </div>
        <div class="d-grid gap-2 mx-auto">
          <input type="submit" class="btn btn-primary" id="signin" value="Login">
        </div>
      </form>
      <div class="text-center small">Don't have an account? <a href="/register">Sign up</a></div>
    </main>
    {% endblock %}
    hashtag
    Device Code

    POST http://app.com/device/code

    The client makes a request to the authorization server to request the device code.

    hashtag
    Request Body

    Name
    Type
    Description

    client_id*

    String

    the client identifier

    scope

    String

    Define the scopes the application has access to

    {
      "device_code": "e2623df1-8594-47b4-b528-41ed3daecc1a",
      "user_code": "56933A",
      "verification_uri": "http://localhost:4000/activate",
      "verification_full": "http://localhost:4000/activate?audience=Pollich Group&user_code=56933A",
      "audience": "Pollich Group",
    
    circle-info

    Note that some authorization servers will allow the device to specify a scope in this request, which will be shown to the user later on the authorization interface.

    After validating the client ID and scopes, the authorization server returns the response with the verification URL, device code, and user code. There are a few optional parameters that the authorization server can return in addition to the example given above.

    • device_code – Required, the verification code generated by the authorization server.

    • user_code – Required, the code the user will enter on the device screen should be relatively short. Typically 6-8 numbers and letters are used.

    • verification_uri – Required, the URL on the authorization server that the user should visit to begin authorization. The user is expected to hand-enter this URL on their computer or mobile phone.

    • expires_in – Optional, the lifetime in seconds of the device code and user code.

    • interval – Optional, the minimum amount of time in seconds that the client should wait between polling requests to the token endpoint.

    hashtag
    Device Activation

    The device shows the verification_uri and user_code to the user on its display, directing the user to enter the code at that URL.

    Visiting that URL after you’ve signed in to your account shows an interface that prompts you to enter the code that’s displayed on the device.

    Meanwhile, the client should attempt to acquire an access token every few seconds (at a rate specified by interval) by POSTing to the access token endpoint on the authorization server.

    hashtag
    Access Token Request

    While the device is waiting for the user to complete the authorization flow on their own computer or phone, the device meanwhile begins polling the token endpoint to request an access token.

    hashtag
    Access Token Request

    POST https://app.com/device/token

    The device makes a POST request with the device_code at the rate specified by interval. The device should continue requesting an access token until a response other than authorization_pending is returned, either the user grants or denies the request or the device code expires.

    hashtag
    Request Body

    Name
    Type
    Description

    grant_type*

    String

    The Device Code grant type value is urn:ietf:params:oauth:grant-type:device_code

    client_id*

    String

    The client id for which the device code was created

    code*

    String

    The value of code should be the device_code from the JSON response in the previous request.

    Environment Variables

    All server settings are defined using environment variables

    Environment Variable

    Default Value

    Description

    CRYSTAL_ENV

    Development

    CRYSTAL_LOG_SOURCES

    "*"

    CRYSTAL_LOG_LEVEL

    Legacy: Implicit grant

    The implicit grant is similar to the authorization code grant with two distinct differences.

    It is intended to be used for user-agent-based clients (e.g. single page web apps) that can’t keep a client secret because all of the application code and storage are easily accessible.

    Secondly, instead of the authorization server returning an authorization code that is exchanged for an access token, the authorization server returns an access token.

    hashtag
    The Flow

    The client will redirect the user to the authorization server with the following parameters in the query string:

    • response_type with the value token

    • client_id with the client identifier

    • redirect_uri with the client redirect URI. This parameter is optional, but if not sent the user will be redirected to a pre-registered redirect URI.

    • scope a space delimited list of scopes

    • state with a token. This parameter is optional but highly recommended. You should store the value of the CSRF token in the user’s session to be validated when they return.

    All of these parameters will be validated by the authorization server.

    The user will then be asked to sign in to the authorization server and approve the client.

    If the user approves the client they will be redirected back to the authorization server with the following parameters in the query string

    Json Web Tokens

    hashtag
    Self-Encoded Access Tokens

    Self-encoded tokens provide a way to avoid storing tokens in a database by encoding all of the necessary information in the token string itself. The main benefit of this is that API servers are able to verify access tokens without doing a database lookup on every API request, making the API much more easily scalable.

    The benefit of OAuth 2.0 Bearer Tokens is that applications don’t need to be aware of how you’ve decided to implement access tokens in your service. This means it’s possible to change your implementation later without affecting clients.

    A common technique for this is using the (JWS) standard to handle encoding, decoding and verification of tokens. The (JWT) specification defines some terms you can use in the JWS, as well as defines some timestamp terms to determine whether a token is valid. We’ll use a JWT library in this example, since it provides built-in handling of expiration.

    {
        // Response
    }
    {
      "Status": "bad_request",
      "Link": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/INTERNAL_SERVER_ERROR",
      "Title": "slow_down",
      "Detail": "",
    }
    {
      "Status": "bad_request",
      "Link": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/INTERNAL_SERVER_ERROR",
      "Title": "authorization_pending, expired_token",
      "Detail": "",
    }
    {
      "Status": "unauthorized",
      "Link": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/INTERNAL_SERVER_ERROR",
      "Title": "access_denied",
      "Detail": "",
    }
    {
      "Status": "unauthorized",
      "Link": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/INTERNAL_SERVER_ERROR",
      "Title": "expired_token",
      "Detail": "",
    }
    POST /device/code HTTP/1.1
    Host: authorization-server.com
    Content-type: application/x-www-form-urlencoded
     
    client_id=a17c21ed&scope=read

    debug

    CRYSTAL_WORKERS

    4

    the number of CPU cores to use

    PORT

    4000

    PORT_REUSE

    true

    HOST

    0.0;0.0

    Binds the server to a particular ip address on the host machine

    DATABASE_URL

    postgres://auth_user:auth_pass@db:5432/authority_db?initial_pool_size=10&checkout_timeout=3P

    PostgreSQL database connection URL

    SECRET_KEY

    secret_key

    The encryption key to use signed JWTs

    CODE_TTL

    5

    Duration in seconds

    ACCESS_TOKEN_TTL

    60

    Duration in seconds

    TEMPLATES_PATH

    ./public/templates

    SESSION_KEY

    session_id

    BASE_URL

    http://localhost:4000arrow-up-right

    DEVICE_CODE_TTL

    300

    Duration in seconds

    SSL_CERT

    ""

    SSL_KEY

    ""

    SSL_CA

    ""

    SSL_MODE

    ""

    JSON Web Signaturearrow-up-right
    JSON Web Tokenarrow-up-right
    GET https://authorization-server.com/authorize?client_id=a17c21ed
    &response_type=code
    &state=5ca75bd30
    &redirect_uri=https%3A%2F%2Fexample-app.com%2Fauth
    &scope=photos
    CSRFarrow-up-right
    {
      "access_token": "AYjcyMzY3ZDhiNmJkNTY",
      "refresh_token": "RjY2NjM5NzA2OWJjuE7c",
      "token_type": "Bearer",
      "expires": 3600
    }
    "expires_in": 300,
    "interval": 5
    }

    OAuth Terms

    As a refresher here is a quick glossary of OAuth terms (taken from the core spec):

    • Resource owner (a.k.a. the User) - An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.

    • Resource server (a.k.a. the API server) - The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.

    • Client - An application making protected resource requests on behalf of the resource owner and with its authorization. The term client does not imply any particular implementation characteristics (e.g. whether the application executes on a server, a desktop, or other devices).

    • Authorization server - The server issues access tokens to the client after successfully authenticating the resource owner and obtaining authorization.

    hashtag
    Access Token Owner

    An access token represents permission granted to a client to access some protected resources.

    If you authorize a machine to access resources and don’t require user permission to access said resources, you should implement the client credentials grant.

    hashtag
    Clients

    Whether or not the client is capable of keeping a secret will depend on which grant the client should use.

    If the client is a web application with a server-side component, you should implement the authorization code grant.

    If the client is a web application that has runs entirely on the front end (e.g., a single page web application), you should implement the password grant for first -arty clients and the implicit grant for a third party clients.

    If the client is a native application such as a mobile app, you should implement the password grant.

    hashtag
    First-Party and Third-Party Clients

    A first-party client is a client that you trust enough to handle the end user’s authorization credentials. For example, Spotify’s iPhone app is owned and developed by Spotify; therefore, they implicitly trust it.

    A third-party client is a client that you don’t trust.

    Client Credentials Flow

    The simplest of all of the OAuth 2.0 grants, this grant is suitable for machine-to-machine authentication where a specific user’s permission to access data is not required.

    The Client Credentials grant type is used by clients to obtain an access token outside of the context of a user. This is typically used by clients to access resources about themselves rather than to access a user's resources.

    hashtag
    Example

    The following is an example authorization code grant the service would receive.

    hashtag
    Client Credentials

    POST https://app.com/token

    In some cases, applications may need an access token to act on behalf of themselves rather than a user. For example, the service may provide a way for the application to update their own information such as their website URL or icon, or they may wish to get statistics about the users of the app. In this case, applications need a way to get an access token for their own account, outside the context of any specific user. OAuth provides the client_credentials grant type for this purpose.

    hashtag
    Headers

    Name
    Type
    Description

    hashtag
    Request Body

    Name
    Type
    Description

    POST /token HTTP/1.1
    Host: authorization-server.com
     
    grant_type=client_credentials
    &client_id=xxxxxxxxxx
    &client_secret=xxxxxxxxxx

    Authorization

    String

    The client needs to authenticate themselves for this request. Typically the service will allow either additional request parameters client_id and client_secret, or accept the client ID and secret in the HTTP Basic auth header.

    grant_type*

    String

    A Parameter must be set to clienst_credentials.

    scope

    String

    The service supports different scopes for the client credentials grant. In practice, not many services actually support this.

    {
      "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
      "token_type":"bearer",
      "expires_in":3600,
      "refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
      "scope":"create"
    }

    Refreshing Access Tokens

    Access tokens eventually expire; however some grants respond with a refresh token which enables the client to get a new access token without requiring the user to be redirected.

    eWhen you initially received the access token, it may have included a refresh token as well as an expiration time like in the example below.

    The presence of the refresh token means that the access token will expire and you’ll be able to get a new one without the user’s interaction.

    The “expires” value is the number of seconds that the access token will be valid. It’s up to the service you’re using to decide how long access tokens will be valid, and may depend on the application or the organization’s own policies. You can use this to preemptively refresh your access tokens instead of waiting for a request with an expired token to fail.

    If you make an API request and the token has expired already, you’ll get back a response indicating as such. You can check for this specific error message, and then refresh the token and try the request again.

    If you’re using a JSON-based API, then it will likely return a JSON error response with the invalid_token error. In any case, the WWW-Authenticate header will also have the invalid_token error.

    When your code recognizes this specific error, it can then make a request to the token endpoint using the refresh token it previously received, and will get back a new access token it can use to retry the original request.

    To use the refresh token, make a POST request to the service’s token endpoint with grant_type=refresh_token, and include the refresh token as well as the client credentials.

    hashtag
    Refresh Access Token

    POST https::/app.com/token

    The refresh token, make a POST request to the service’s token endpoint with grant_type=refresh_token, and include the refresh token as well as the client credentials.

    hashtag
    Headers

    Name
    Type
    Description

    hashtag
    Request Body

    Name
    Type
    Description
    {
      "access_token": "AYjcyMzY3ZDhiNmJkNTY",
      "refresh_token": "RjY2NjM5NzA2OWJjuE7c",
      "token_type": "bearer",
      "expires": 3600
    }
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: Bearer error="invalid_token"
      error_description="The access token expired"
    Content-type: application/json
     
    {
      "error": "invalid_token",
      "error_description": "The access token expired"
    }

    Authorization*

    String

    The client needs to authenticate themselves for this request. Typically the service will allow either additional request parameters client_id and client_secret, or accept the client ID and secret in the HTTP Basic auth header.

    grant_type*

    String

    Must be set to refresh_token

    refresh_token*

    String

    The curent refresh token

    POST /token HTTP/1.1
    Host: authorization-server.com
     
    grant_type=refresh_token
    &refresh_token=xxxxxxxxxxx
    &client_id=xxxxxxxxxx
    &client_secret=xxxxxxxxxx
    {
      "access_token": "BWjcyMzY3ZDhiNmJkNTY",
      "refresh_token": "Srq2NjM5NzA2OWJjuE7c",
      "token_type": "bearer",
      "expires": 3600
    }

    Introduction

    Authority is an authentication solution built with the Crystal programming language. It offers robust authentication features, including OAuth grants and customizable authentication logic. The following documentation will guide you through the installation, configuration, and usage of the Authority project.

    Authorization Flow

    The authorization code grant should be very familiar if you’ve ever signed into an application using your Facebook or Google account.

    The authorization code grant is used when an application exchanges an authorization code for an access token. After the user returns to the application via the redirect URL, the application will get the authorization code from the URL and use it to request an access token. This request will be made to the token endpoint.

    hashtag
    The Flow (Part One)

    The client will redirect the user to the authorization server with the following parameters in the query string:

    hashtag
    Authorization Code

    GET https://authorization-server.com/authorize

    The client will redirect the user to the authorization server with the following parameters in the query string:

    hashtag
    Query Parameters

    Name
    Type
    Description
    circle-info

    You should first compare this state value to ensure it matches the one you started with. You can typically store the state value in a cookie or session, and compare it when the user comes back. This helps ensure your redirection endpoint isn't able to be tricked into attempting to exchange arbitrary authorization codes.

    The parameters will be validated by the authorization server.

    hashtag
    User Authorization Prompt

    The user will then be asked to sign in to the authorization server and approve the client.

    The user sees the authorization prompt

    If the user approves the client they will be redirected from the authorization server back to the client (specifically to the redirect URI) with the following parameters in the query string:

    • code with the authorization code

    • state with the state parameter sent in the original request. You should compare this value with the value stored in the user’s session to ensure the authorization code obtained is in response to requests made by this client rather than another client application.

    hashtag
    PKCE Extension

    The Proof Key for Code Exchange (PKCE, pronounced pixie) extension describes a technique for public clients to mitigate the threat of having the authorization code intercepted. The technique involves the client first creating a secret, and then using that secret again when exchanging the authorization code for an access token. This way if the code is intercepted, it will not be useful since the token request relies on the initial secret.

    Once the app has generated the code verifier, it uses that to create the code challenge. For devices that can perform a SHA256 hash, the code challenge is a BASE64-URL-encoded string of the SHA256 hash of the code verifier. Clients that do not have the ability to perform a SHA256 hash are permitted to use the plain code verifier string as the challenge.

    Now that the client has a code challenge string, it includes that and a parameter that indicates which method was used to generate the challenge (plain or S256) along with the standard parameters of the authorization request. This means a complete authorization request will include the following parameters.

    circle-check

    The PKCE extension does not add any new responses, so clients can always use the PKCE extension even if an authorization server does not support it.

    hashtag
    The Flow (Part Two)

    Exchange the authorization code for an access token

    To exchange the authorization code for an access token, the app makes a POST request to the service’s token endpoint. The request will have the following parameters.

    hashtag
    Creates an Access Token

    POST https://my-auth-server.com/token

    The server exchanges the authorization code for an access token by making a POST request to the token endpoint.

    hashtag
    Headers

    Name
    Type
    Description

    hashtag
    Request Body

    Name
    Type
    Description

    OAuth Security

    Up until 2019, the OAuth 2.0 spec only recommended using the extension for mobile and JavaScript apps. The latest OAuth Security BCP now recommends using PKCE also for server-side apps, as it provides some additional benefits there as well. It is likely to take some time before common OAuth services adapt to this new recommendation, but if you’re building a server from scratch you should definitely support PKCE for all types of clients.

    GET https://authorization-server.com/authorize?client_id=a17c21ed
    &response_type=code
    &state=5ca75bd30
    &redirect_uri=https%3A%2F%2Fexample-app.com%2Fauth
    &scope=photos

    state

    String

    with a token. This parameter is optional but highly recommended.

    response_type*

    String

    Indicates that your server expects to receive an authorization code. Must be code

    client_id*

    String

    The client ID you received when you first registered the application

    redirect_uri*

    String

    Indicates the URI to return the user to after authorization is complete

    scope*

    String

    One or more scope values indicating which parts of the user's account you wish to access

    Authorization*

    String

    Contains the word Basic, followed by a space and a base64-encoded(non-encrypted) string with the client id and client secret

    grant_type*

    String

    The grant type for this flow is authorization_code

    redirect_uri*

    String

    Must be identical to the redirect URI provided in the original link

    code*

    String

    The authorization code from the query string

    code_verifier

    String

    PCKE Extension - the code verifier for the PKCE request, that the app originally generated before the authorization request.

    PKCEarrow-up-right

    Legacy: Password

    The Password grant is used when the application exchanges the user’s username and password for an access token.

    circle-exclamation

    This is exactly the thing OAuth was created to prevent in the first place, so you should never allow third-party apps to use this grant.

    A common use for this grant type is to enable password logins for your service’s own apps. Users won’t be surprised to log in to the service’s website or native application using their username and password, but third-party apps should never be allowed to ask the user for their password.

    hashtag
    Example

    The following is an example password grant the service would receive.

    See for details on the parameters to return when generating an access token or responding to errors.

    https://example-app.com/cb?code=AUTH_CODE_HERE&state=1234zyx
    https://example-app.com/cb?code=AUTH_CODE_HERE&state=1234zyx
    GET https://authorization-server.com/authorize?client_id=a17c21ed
    &response_type=code
    &state=5ca75bd30
    &redirect_uri=https%3A%2F%2Fexample-app.com%2Fauth
    &scope=photos
    &code_challenge=XXXXXXXX
    &code_challenge_method=S256
    POST /oauth/token HTTP/1.1
    Host: authorization-server.com
     
    code=Yzk5ZDczMzRlNDEwY
    &grant_type=code
    &redirect_uri=https://example-app.com/cb
    &client_id=mRkZGFjM
    &client_secret=ZGVmMjMz
    &code_verifier=a6b602d858ae0da189dacd297b188ef308dc754bd9cc359ac2e1d8d1
    {
      "access_token": "AYjcyMzY3ZDhiNmJkNTY",
      "refresh_token": "RjY2NjM5NzA2OWJjuE7c",
      "token_type": "Bearer",
      "expires": 3600
    }
    POST /oauth/token HTTP/1.1
    Host: authorization-server.com
     
    grant_type=password
    &username=user@example.com
    &password=1234luggage
    &client_id=xxxxxxxxxx
    &client_secret=xxxxxxxxxx
    
    Access Token Responsearrow-up-right
    CSRFarrow-up-right

    Access Token Response

    hashtag
    Successful Response

    If the request for an access token is valid, the authorization server needs to generate an access token (and optional refresh token) and return these to the client, typically along with some additional properties about the authorization.

    For example, a successful token response may look like the following:

    HTTP/1.1 200 OK
    Content-Type: application/json
    Cache-Control: no-store
    Pragma: no-cache
     
    {
      "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
      "token_type":"bearer",
      "expires_in":3600,
      "refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
      "scope":"create"
    }

    hashtag
    Access Tokens

    The format for OAuth 2.0 Bearer tokens is actually described in a separate spec, . There is no defined structure for the token required by the spec, so you can generate a string and implement tokens however you want. The valid characters in a bearer token are alphanumeric, and the following punctuation characters:

    -._~+/

    RFC 6750arrow-up-right

    Open ID Connect

    OpenID Connect provides user identity and authentication on top of the OAuth 2.0 framework. You can use OpenID Connect to establish a login session, and use OAuth to access protected resources.

    You can request both an ID token and access token in the same flow in order to both authenticate the user as well as obtain authorization to access a protected resource.

    OpenID Connect is maintained by the OpenID Foundationarrow-up-right. The core OpenID Connect spec, as well as many extensions, can be read in full on https://openid.net/connect/arrow-up-right.

    The OpenID Connect Debuggerarrow-up-right is a fantastic resource to help you build OpenID Connect requests and walk through the flows. Additionally, the OAuth 2.0 Playgroundarrow-up-right provides a walkthrough of the OpenID Connect flow against a live server.

    Configurationchevron-rightUser Infochevron-rightRegistering Clientschevron-right

    Registering Clients

    When a developer comes to your website, they will need a way to create a new application and obtain credentials. Typically you will have them create a developer account, or create an account on behalf of their organization, before they can create an application.

    While the OAuth 2.0 spec doesn’t require you to collect any application information in particular before granting credentials, most services collect basic information about an app, such as the app name and an icon, before issuing the client_id and client_secret. It is, however, important that you require the developer to register one or more redirect URLs for the application for security purposes. This is explained in more detail in Redirect URLsarrow-up-right.

    Typically services collect information about an application such as:

    • Application name

    • An icon for the application

    • URL to the application’s home page

    • A short description of the application

    • A link to the application’s privacy policy

    • A list of redirect URLs

    hashtag
    The Client ID and Secret

    Client ID

    The client_id is a public identifier for apps. Even though it’s public, it’s best that it isn’t guessable by third parties, so many implementations use something like a 32-character hex string. It must also be unique across all clients that the authorization server handles. If the client ID is guessable, it makes it slightly easier to craft phishing attacks against arbitrary applications.

    Client Secret

    The client_secret is a secret known only to the application and the authorization server. It must be sufficiently random to not be guessable, which means you should avoid using common UUID libraries which often take into account the timestamp or MAC address of the server generating it. A great way to generate a secure secret is to use a cryptographically-secure library to generate a 256-bit value and convert it to a hexadecimal representation.

    Specs

    The project specifications can be found in the specs directory. Use the directory to get an idea of the project capabilities and configuration.

    Running Specs

    If you have all the requirements installed, running the specs should be fairly simple. Run the following commands to run the specs locally

    shards build server
    crystal specs
    circle-info

    Ensure you have a Postgres database process running with the correct credentials

    Headless Mode

    Specs run using the Flux shard, this allows for browser testing. Currently, the configuration is set to run headless by default, which means that you will not see the browser interactions, if you wish to change this behavior simply remove the `-headless` parameter for the spec/flows files

    def initialize(@url : String, @username : String, @password : String)
      options = Marionette.firefox_options(args: ["-headless"])
      super(Marionette::Browser::Firefox, options)
    end

    Security Considerations

    Security is a critical aspect of the Authority authentication system. Below are some key considerations:

    • Token Management: Ensure that OAuth tokens are stored securely and are not exposed to unauthorized users.

    • Access Control: Implement proper access control mechanisms to ensure that only authorized users can access sensitive data.

    • Encryption: Always use HTTPS to encrypt communication between the client and the server.

    User Info

    Configuration

    API Endpoints

    This section documents all the available API endpoints in the Authority project. Each endpoint serves a specific purpose, such as managing OAuth clients, handling user sessions, or authorizing users.

    hashtag
    1. Clients Endpoints

    The clients endpoints manage OAuth clients that represent applications interacting with the Authority system.

    • POST /clients: Create a new OAuth client.

      Example Request:

      Example Response:

    • GET /clients: Retrieve a list of registered OAuth clients.

      Example Response:

    hashtag
    2. Owner Endpoints

    The owner endpoints manage resource owners, allowing the Authority system to verify and manage access to resources owned by users.

    • GET /owner: Retrieve information about the authenticated resource owner.

      Example Response:

    hashtag
    3. Sessions Endpoints

    The sessions endpoints manage user sessions, including login and logout functionality.

    • POST /sessions/login: Authenticate a user and create a session.

      Example Request:

      Example Response:

    • POST /sessions/logout: Log out the authenticated user and invalidate the session.

      Example Response:

    hashtag
    4. Authorize Endpoints

    The authorize endpoints manage the OAuth authorization flow.

    • GET /authorize: Redirect users to the OAuth provider for authorization.

      • Example Response: Redirects the user to the OAuth provider's login page.

    • POST /authorize: Handle the authorization code returned by the OAuth provider and exchange it for an access token.

      Example Request:

    hashtag
    5. Device Endpoints

    The device endpoints manage device-specific interactions, such as registering or authenticating devices.

    • POST /device/register: Register a new device.

      Example Request:

      Example Response:

    hashtag
    6. Access Token Endpoints

    The access_token endpoints handle the management of access tokens, including issuing, refreshing, and revoking tokens.

    • POST /access_token: Exchange an authorization code for an access token.

      Example Request:

      Example Response:

    • POST /access_token/revoke: Revoke an access token.

      Example Request:

      Example Response:

    hashtag
    7. Health Check

    The health_check.cr endpoint is used to check the health of the Authority service.

    • GET /health_check: Returns the status of the service.

      Example Response:

    Example Response:
    {
      "name": "My App",
      "redirect_uri": "https://myapp.com/callback"
    }
    {
      "client_id": "abc123",
      "client_secret": "xyz789"
    }
    [
      {
        "client_id": "abc123",
        "name": "My App",
        "redirect_uri": "https://myapp.com/callback"
      }
    ]
    {
      "id": 1,
      "name": "John Doe",
      "email": "johndoe@example.com"
    }
    {
      "email": "user@example.com",
      "password": "password123"
    }
    {
      "access_token": "token123"
    }
    {
      "message": "Logged out successfully"
    }
    {
      "authorization_code": "code123"
    }
    {
      "device_id": "device123",
      "device_name": "John's Phone"
    }
    {
      "message": "Device registered successfully"
    }
    {
      "authorization_code": "code123"
    }
    {
      "access_token": "token123",
      "expires_in": 3600
    }
    {
      "access_token": "token123"
    }
    {
      "message": "Access token revoked"
    }
    {
      "status": "healthy"
    }
    {
      "access_token": "token123"
    }

    hashtag
    Get a registred client.

    get

    See information about a registred client.

    Path parameters
    client_idstringRequired

    ID of the client

    Header parameters
    AuthorizationstringRequired

    Bearer token obtained on the register process through the registration_access_token property giving access only to one client matching the client_id path parameter. An admin token can be also obtained through the client crendentials flow with as mandatory scope "dcr_admin".

    Responses
    chevron-right
    200

    Claims about the registred client.

    application/json
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    chevron-right
    403

    Access forbidden

    get
    /register/{client_id}

    hashtag
    Delete a registred client.

    delete

    Delete a registred client.

    Path parameters
    client_idstringRequired

    ID of the client

    Header parameters
    AuthorizationstringRequired

    Bearer token obtained on the register process through the registration_access_token property giving access only to one client matching the client_id path parameter. An admin token can be also obtained through the client crendentials flow with as mandatory scope "dcr_admin".

    Responses
    chevron-right
    204

    Client deleted

    */*
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    chevron-right
    403

    Access forbidden

    delete
    /register/{client_id}

    hashtag
    Patch a registred client.

    patch

    Update information about a registred client.

    Path parameters
    client_idstringRequired

    ID of the client

    Header parameters
    AuthorizationstringRequired

    Bearer token obtained on the register process through the registration_access_token property giving access only to one client matching the client_id path parameter. An admin token can be also obtained through the client crendentials flow with as mandatory scope "dcr_admin".

    Body
    redirect_urisstring[]Required

    REQUIRED. Array of Redirection URI values used by the Client. One of these registered Redirection URI values MUST exactly match the redirect_uri parameter value used in each Authorization Request

    response_typesstring[]Optional

    JSON array containing a list of the OAuth 2.0 response_type values that the Client is declaring that it will restrict itself to using. If omitted, the default is that the Client will use only the code Response Type.

    grant_typesstring[]Optional

    JSON array containing a list of the OAuth 2.0 Grant Types that the Client is declaring that it will restrict itself to using. Values used by OpenID Connect are authorization_code, implicit and refresh_token

    application_typestringOptional

    Kind of the application. The default, if omitted, is web. The defined values are native or web.

    contactsstring[]Optional

    Array of e-mail addresses of people responsible for this Client. This might be used by some providers to enable a Web user interface to modify the Client information.

    client_namestringOptional

    Name of the Client to be presented to the End-User.

    logo_uristringOptional

    URL that references a logo for the Client application.

    client_uristringOptional

    URL of the home page of the Client. The value of this field MUST point to a valid Web page.

    policy_uristringOptional

    URL that the Relying Party Client provides to the End-User to read about the how the profile data will be used.

    tos_uristringOptional

    URL that the Relying Party Client provides to the End-User to read about the Relying Party's terms of service.

    jwks_uristringOptional

    URL for the Client's JSON Web Key Set [JWK] document.

    sector_identifier_uristringOptional

    URL using the https scheme to be used in calculating Pseudonymous Identifiers by the OP. The URL references a file with a single JSON array of redirect_uri values.

    subject_typestringOptional

    subject_type requested for responses to this Client. The subject_types_supported Discovery parameter contains a list of the supported subject_type values for this server. Valid types include pairwise and public.

    id_token_signed_response_algstringOptional

    JWS alg algorithm [JWA] REQUIRED for signing the ID Token issued to this Client. The default, if omitted, is RS256. The public key for validating the signature is provided by retrieving the JWK Set referenced by the jwks_uri element from OpenID Connect Discovery 1.0 [OpenID.Discovery].

    id_token_encrypted_response_algstringOptional

    JWE alg algorithm [JWA] REQUIRED for encrypting the ID Token issued to this Client. If this is requested, the response will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that no encryption is performed.

    id_token_encrypted_response_encstringOptional

    JWE enc algorithm [JWA] REQUIRED for encrypting the ID Token issued to this Client. If id_token_encrypted_response_alg is specified, the default for this value is A128CBC-HS256. When id_token_encrypted_response_enc is included, id_token_encrypted_response_alg MUST also be provided.

    userinfo_signed_response_algstringOptional

    WS alg algorithm [JWA] REQUIRED for signing UserInfo Responses. If this is specified, the response will be JWT [JWT] serialized, and signed using JWS. The default, if omitted, is for the UserInfo Response to return the Claims as a UTF-8 encoded JSON object using the application/json content-type.

    userinfo_encrypted_response_algstringOptional

    JWE [JWE] alg algorithm [JWA] REQUIRED for encrypting UserInfo Responses. If both signing and encryption are requested, the response will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that no encryption is performed.

    userinfo_encrypted_response_encstringOptional

    JWE enc algorithm [JWA] REQUIRED for encrypting UserInfo Responses. If userinfo_encrypted_response_alg is specified, the default for this value is A128CBC-HS256. When userinfo_encrypted_response_enc is included, userinfo_encrypted_response_alg MUST also be provided.

    request_object_signing_algstringOptional

    JWS [JWS] alg algorithm [JWA] that MUST be used for signing Request Objects sent to the OP. All Request Objects from this Client MUST be rejected, if not signed with this algorithm. Request Objects are described in Section 6.1 of OpenID Connect Core 1.0 [OpenID.Core]. This algorithm MUST be used both when the Request Object is passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter). Servers SHOULD support RS256. The value none MAY be used. The default, if omitted, is that any algorithm supported by the OP and the RP MAY be used.

    request_object_encryption_algstringOptional

    JWE [JWE] alg algorithm [JWA] the RP is declaring that it may use for encrypting Request Objects sent to the OP. This parameter SHOULD be included when symmetric encryption will be used, since this signals to the OP that a client_secret value needs to be returned from which the symmetric key will be derived, that might not otherwise be returned. The RP MAY still use other supported encryption algorithms or send unencrypted Request Objects, even when this parameter is present. If both signing and encryption are requested, the Request Object will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that the RP is not declaring whether it might encrypt any Request Objects.

    request_object_encryption_encstringOptional

    JWE enc algorithm [JWA] the RP is declaring that it may use for encrypting Request Objects sent to the OP. If request_object_encryption_alg is specified, the default for this value is A128CBC-HS256. When request_object_encryption_enc is included, request_object_encryption_alg MUST also be provided.

    token_endpoint_auth_methodstringOptional

    Requested Client Authentication method for the Token Endpoint. The options are client_secret_post, client_secret_basic, client_secret_jwt, private_key_jwt, and none, as described in Section 9 of OpenID Connect Core 1.0 [OpenID.Core]. Other authentication methods MAY be defined by extensions. If omitted, the default is client_secret_basic -- the HTTP Basic Authentication Scheme specified in Section 2.3.1 of OAuth 2.0 [RFC6749].

    token_endpoint_auth_signing_algstringOptional

    JWS [JWS] alg algorithm [JWA] that MUST be used for signing the JWT [JWT] used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods. All Token Requests using these authentication methods from this Client MUST be rejected, if the JWT is not signed with this algorithm. Servers SHOULD support RS256. The value none MUST NOT be used. The default, if omitted, is that any algorithm supported by the OP and the RP MAY be used.

    default_max_ageintegerOptional

    Default Maximum Authentication Age. Specifies that the End-User MUST be actively authenticated if the End-User was authenticated longer ago than the specified number of seconds. The max_age request parameter overrides this default value. If omitted, no default Maximum Authentication Age is specified.

    require_auth_timebooleanOptional

    Boolean value specifying whether the auth_time Claim in the ID Token is REQUIRED. It is REQUIRED when the value is true.

    default_acr_valuesstring[]Optional

    Default requested Authentication Context Class Reference values. Array of strings that specifies the default acr values that the OP is being requested to use for processing requests from this Client, with the values appearing in order of preference.

    initiate_login_uristringOptional

    URI using the https scheme that a third party can use to initiate a login by the RP, as specified in Section 4 of OpenID Connect Core 1.0 [OpenID.Core].

    request_urisstring[]Optional

    Array of request_uri values that are pre-registered by the RP for use at the OP.

    scopestring[]Optional

    String containing a space-separated list of scope values

    software_idstringOptional

    A unique identifier string (e.g., a Universally Unique Identifier (UUID)) assigned by the client developer or software publisher used by registration endpoints to identify the client software to be dynamically registered.

    software_versionstringOptional

    A version identifier string for the client software identified by "software_id". The value of the "software_version" SHOULD change on any update to the client software identified by the same "software_id".

    software_statementstringOptional

    A software statement containing client metadata values about the client software as claims. This is a string value containing the entire signed JWT.

    Responses
    chevron-right
    200

    Claims about the updated client.

    application/json
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    chevron-right
    403

    Access forbidden

    patch
    /register/{client_id}

    hashtag
    Register (create) a new client.

    post

    The Dynamic Client Registration (dcr) Endpoint is an OAuth 2.0 Protected Resource through which a new Client registration can be requested.

    Header parameters
    AuthorizationstringOptional

    Bearer token obtained through client crendentials flow with as mandatory scope "dcr_admin". Token required unless open dynamic client registration is enabled.

    Body
    redirect_urisstring[]Required

    REQUIRED. Array of Redirection URI values used by the Client. One of these registered Redirection URI values MUST exactly match the redirect_uri parameter value used in each Authorization Request

    response_typesstring[]Optional

    JSON array containing a list of the OAuth 2.0 response_type values that the Client is declaring that it will restrict itself to using. If omitted, the default is that the Client will use only the code Response Type.

    grant_typesstring[]Optional

    JSON array containing a list of the OAuth 2.0 Grant Types that the Client is declaring that it will restrict itself to using. Values used by OpenID Connect are authorization_code, implicit and refresh_token

    application_typestringOptional

    Kind of the application. The default, if omitted, is web. The defined values are native or web.

    contactsstring[]Optional

    Array of e-mail addresses of people responsible for this Client. This might be used by some providers to enable a Web user interface to modify the Client information.

    client_namestringOptional

    Name of the Client to be presented to the End-User.

    logo_uristringOptional

    URL that references a logo for the Client application.

    client_uristringOptional

    URL of the home page of the Client. The value of this field MUST point to a valid Web page.

    policy_uristringOptional

    URL that the Relying Party Client provides to the End-User to read about the how the profile data will be used.

    tos_uristringOptional

    URL that the Relying Party Client provides to the End-User to read about the Relying Party's terms of service.

    jwks_uristringOptional

    URL for the Client's JSON Web Key Set [JWK] document.

    sector_identifier_uristringOptional

    URL using the https scheme to be used in calculating Pseudonymous Identifiers by the OP. The URL references a file with a single JSON array of redirect_uri values.

    subject_typestringOptional

    subject_type requested for responses to this Client. The subject_types_supported Discovery parameter contains a list of the supported subject_type values for this server. Valid types include pairwise and public.

    id_token_signed_response_algstringOptional

    JWS alg algorithm [JWA] REQUIRED for signing the ID Token issued to this Client. The default, if omitted, is RS256. The public key for validating the signature is provided by retrieving the JWK Set referenced by the jwks_uri element from OpenID Connect Discovery 1.0 [OpenID.Discovery].

    id_token_encrypted_response_algstringOptional

    JWE alg algorithm [JWA] REQUIRED for encrypting the ID Token issued to this Client. If this is requested, the response will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that no encryption is performed.

    id_token_encrypted_response_encstringOptional

    JWE enc algorithm [JWA] REQUIRED for encrypting the ID Token issued to this Client. If id_token_encrypted_response_alg is specified, the default for this value is A128CBC-HS256. When id_token_encrypted_response_enc is included, id_token_encrypted_response_alg MUST also be provided.

    userinfo_signed_response_algstringOptional

    WS alg algorithm [JWA] REQUIRED for signing UserInfo Responses. If this is specified, the response will be JWT [JWT] serialized, and signed using JWS. The default, if omitted, is for the UserInfo Response to return the Claims as a UTF-8 encoded JSON object using the application/json content-type.

    userinfo_encrypted_response_algstringOptional

    JWE [JWE] alg algorithm [JWA] REQUIRED for encrypting UserInfo Responses. If both signing and encryption are requested, the response will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that no encryption is performed.

    userinfo_encrypted_response_encstringOptional

    JWE enc algorithm [JWA] REQUIRED for encrypting UserInfo Responses. If userinfo_encrypted_response_alg is specified, the default for this value is A128CBC-HS256. When userinfo_encrypted_response_enc is included, userinfo_encrypted_response_alg MUST also be provided.

    request_object_signing_algstringOptional

    JWS [JWS] alg algorithm [JWA] that MUST be used for signing Request Objects sent to the OP. All Request Objects from this Client MUST be rejected, if not signed with this algorithm. Request Objects are described in Section 6.1 of OpenID Connect Core 1.0 [OpenID.Core]. This algorithm MUST be used both when the Request Object is passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter). Servers SHOULD support RS256. The value none MAY be used. The default, if omitted, is that any algorithm supported by the OP and the RP MAY be used.

    request_object_encryption_algstringOptional

    JWE [JWE] alg algorithm [JWA] the RP is declaring that it may use for encrypting Request Objects sent to the OP. This parameter SHOULD be included when symmetric encryption will be used, since this signals to the OP that a client_secret value needs to be returned from which the symmetric key will be derived, that might not otherwise be returned. The RP MAY still use other supported encryption algorithms or send unencrypted Request Objects, even when this parameter is present. If both signing and encryption are requested, the Request Object will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that the RP is not declaring whether it might encrypt any Request Objects.

    request_object_encryption_encstringOptional

    JWE enc algorithm [JWA] the RP is declaring that it may use for encrypting Request Objects sent to the OP. If request_object_encryption_alg is specified, the default for this value is A128CBC-HS256. When request_object_encryption_enc is included, request_object_encryption_alg MUST also be provided.

    token_endpoint_auth_methodstringOptional

    Requested Client Authentication method for the Token Endpoint. The options are client_secret_post, client_secret_basic, client_secret_jwt, private_key_jwt, and none, as described in Section 9 of OpenID Connect Core 1.0 [OpenID.Core]. Other authentication methods MAY be defined by extensions. If omitted, the default is client_secret_basic -- the HTTP Basic Authentication Scheme specified in Section 2.3.1 of OAuth 2.0 [RFC6749].

    token_endpoint_auth_signing_algstringOptional

    JWS [JWS] alg algorithm [JWA] that MUST be used for signing the JWT [JWT] used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods. All Token Requests using these authentication methods from this Client MUST be rejected, if the JWT is not signed with this algorithm. Servers SHOULD support RS256. The value none MUST NOT be used. The default, if omitted, is that any algorithm supported by the OP and the RP MAY be used.

    default_max_ageintegerOptional

    Default Maximum Authentication Age. Specifies that the End-User MUST be actively authenticated if the End-User was authenticated longer ago than the specified number of seconds. The max_age request parameter overrides this default value. If omitted, no default Maximum Authentication Age is specified.

    require_auth_timebooleanOptional

    Boolean value specifying whether the auth_time Claim in the ID Token is REQUIRED. It is REQUIRED when the value is true.

    default_acr_valuesstring[]Optional

    Default requested Authentication Context Class Reference values. Array of strings that specifies the default acr values that the OP is being requested to use for processing requests from this Client, with the values appearing in order of preference.

    initiate_login_uristringOptional

    URI using the https scheme that a third party can use to initiate a login by the RP, as specified in Section 4 of OpenID Connect Core 1.0 [OpenID.Core].

    request_urisstring[]Optional

    Array of request_uri values that are pre-registered by the RP for use at the OP.

    scopestring[]Optional

    String containing a space-separated list of scope values

    software_idstringOptional

    A unique identifier string (e.g., a Universally Unique Identifier (UUID)) assigned by the client developer or software publisher used by registration endpoints to identify the client software to be dynamically registered.

    software_versionstringOptional

    A version identifier string for the client software identified by "software_id". The value of the "software_version" SHOULD change on any update to the client software identified by the same "software_id".

    software_statementstringOptional

    A software statement containing client metadata values about the client software as claims. This is a string value containing the entire signed JWT.

    Responses
    chevron-right
    201

    Claims about the registred client

    application/json
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    chevron-right
    403

    Registration forbidden

    post
    /register

    hashtag
    Renew the client secret of a registred client.

    post

    Renew the client secret of a registred client.

    Path parameters
    client_idstringRequired

    ID of the client

    Header parameters
    AuthorizationstringRequired

    Bearer token obtained on the register process through the registration_access_token property giving access only to one client matching the client_id path parameter. An admin token can be also obtained through the client crendentials flow with as mandatory scope "dcr_admin".

    Responses
    chevron-right
    200

    Claims about the updated client.

    application/json
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    chevron-right
    403

    Access forbidden

    post
    /register/{client_id}/renew_secret

    hashtag
    Get claims about the authenticated End-User

    get

    The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User.

    Header parameters
    AuthorizationstringRequired

    To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication

    Responses
    chevron-right
    200

    Claims about the authenticated End-User

    application/json
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    get
    /userinfo

    hashtag
    Get claims about the authenticated End-User

    post

    The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User.

    Body
    access_tokenstringRequired

    To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication

    Responses
    chevron-right
    200

    Claims about the authenticated End-User

    application/json
    chevron-right
    400

    Invalid Request

    chevron-right
    401

    Invalid Token

    post
    /userinfo

    hashtag
    Get JSON Web Key Set

    get

    JWKS endpoint containing the public keys used by OpenID Connect Relying Party to verify any JWT issued by the authorization server.

    Responses
    chevron-right
    200

    A JSON object that represents a set of JWKs

    application/json
    get
    /.well-known/jwks.json
    200

    A JSON object that represents a set of JWKs

    GET /unknown/.well-known/jwks.json HTTP/1.1
    Host: auth.authority.io
    Accept: */*
    
    {
      "client_id": "text",
      "client_secret": "text",
      "registration_access_token": "text",
      "registration_client_uri": "text",
      "client_id_issued_at": "text",
      "client_secret_expires_at": 1,
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    {
      "client_id": "text",
      "client_secret": "text",
      "registration_access_token": "text",
      "registration_client_uri": "text",
      "client_id_issued_at": "text",
      "client_secret_expires_at": 1,
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    {
      "client_id": "text",
      "client_secret": "text",
      "registration_access_token": "text",
      "registration_client_uri": "text",
      "client_id_issued_at": "text",
      "client_secret_expires_at": 1,
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    {
      "client_id": "text",
      "client_secret": "text",
      "registration_access_token": "text",
      "registration_client_uri": "text",
      "client_id_issued_at": "text",
      "client_secret_expires_at": 1,
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    {
      "client_id": "text",
      "client_secret": "text",
      "registration_access_token": "text",
      "registration_client_uri": "text",
      "client_id_issued_at": "text",
      "client_secret_expires_at": 1,
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    GET /unknown/register/{client_id} HTTP/1.1
    Host: auth.authority.io
    Authorization: text
    Accept: */*
    
    DELETE /unknown/register/{client_id} HTTP/1.1
    Host: auth.authority.io
    Authorization: text
    Accept: */*
    
    PATCH /unknown/register/{client_id} HTTP/1.1
    Host: auth.authority.io
    Authorization: text
    Content-Type: application/json
    Accept: */*
    Content-Length: 1084
    
    {
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    POST /unknown/register HTTP/1.1
    Host: auth.authority.io
    Content-Type: application/json
    Accept: */*
    Content-Length: 1084
    
    {
      "redirect_uris": [
        "text"
      ],
      "response_types": [
        "text"
      ],
      "grant_types": [
        "text"
      ],
      "application_type": "text",
      "contacts": [
        "text"
      ],
      "client_name": "text",
      "logo_uri": "text",
      "client_uri": "text",
      "policy_uri": "text",
      "tos_uri": "text",
      "jwks_uri": "text",
      "jwks": {
        "keys": [
          {
            "kty": "text",
            "use": "text",
            "key_ops": "text",
            "alg": "text",
            "kid": "text",
            "x5u": "text",
            "x5c": "text",
            "x5t": "text",
            "x5t#S256": "text"
          }
        ]
      },
      "sector_identifier_uri": "text",
      "subject_type": "text",
      "id_token_signed_response_alg": "text",
      "id_token_encrypted_response_alg": "text",
      "id_token_encrypted_response_enc": "text",
      "userinfo_signed_response_alg": "text",
      "userinfo_encrypted_response_alg": "text",
      "userinfo_encrypted_response_enc": "text",
      "request_object_signing_alg": "text",
      "request_object_encryption_alg": "text",
      "request_object_encryption_enc": "text",
      "token_endpoint_auth_method": "text",
      "token_endpoint_auth_signing_alg": "text",
      "default_max_age": 1,
      "require_auth_time": true,
      "default_acr_values": [
        "text"
      ],
      "initiate_login_uri": "text",
      "request_uris": [
        "text"
      ],
      "scope": [
        "text"
      ],
      "software_id": "text",
      "software_version": "text",
      "software_statement": "text"
    }
    POST /unknown/register/{client_id}/renew_secret HTTP/1.1
    Host: auth.authority.io
    Authorization: text
    Accept: */*
    
    {
      "sub": "text",
      "name": "text",
      "given_name": "text",
      "family_name": "text",
      "middle_name": "text",
      "nickname": "text",
      "preferred_username": "text",
      "profile": "text",
      "picture": "text",
      "website": "text",
      "email": "text",
      "email_verified": true,
      "gender": "text",
      "birthdate": "text",
      "zoneinfo": "text",
      "locale": "text",
      "phone_number": "text",
      "phone_number_verified": true,
      "address": "text",
      "updated_at": 1
    }
    {
      "sub": "text",
      "name": "text",
      "given_name": "text",
      "family_name": "text",
      "middle_name": "text",
      "nickname": "text",
      "preferred_username": "text",
      "profile": "text",
      "picture": "text",
      "website": "text",
      "email": "text",
      "email_verified": true,
      "gender": "text",
      "birthdate": "text",
      "zoneinfo": "text",
      "locale": "text",
      "phone_number": "text",
      "phone_number_verified": true,
      "address": "text",
      "updated_at": 1
    }
    GET /unknown/userinfo HTTP/1.1
    Host: auth.authority.io
    Authorization: text
    Accept: */*
    
    POST /unknown/userinfo HTTP/1.1
    Host: auth.authority.io
    Content-Type: application/x-www-form-urlencoded
    Accept: */*
    Content-Length: 23
    
    "access_token='text'"
    {
      "keys": [
        {
          "kty": "text",
          "use": "text",
          "key_ops": "text",
          "alg": "text",
          "kid": "text",
          "x5u": "text",
          "x5c": "text",
          "x5t": "text",
          "x5t#S256": "text"
        }
      ]
    }