Tutorial: Setting Up the OAuth2 Server

Setting Up the OAuth2 Server

Besides providing compatibility with OAuth2 login sources, Flitter Auth ships with the ability to use your application as an OAuth2 server as well. This would allow other applications to implement "Sign in with X" buttons that redirect users to your application, have them sign in, then redirect back.

Again, by default the only supported grant type is authorization_code.

Conceptual

OAuth2 authentication is a fundamentally different way of authenticating a user (as compared to the local database-driven auth, and the LDAP auth). Rather than providing a username and password to a login form on your application, the application redirects the user to the login page for a different provider.

Once the user has signed in with your application, your application redirects the user back to a specific endpoint on the client application with a special token known as an authorization code. That application then takes this authorization code and (by making a web request from the server itself) redeems this authorization code for a bearer token, which can be used to access some API endpoint on your application.

Using that API bearer token, the client makes another request (again from the server) to a configured API endpoint on your application (authenticating with the bearer token) to retrieve information about the user.

Configuration

The configuration for the OAuth2 server is located in the config/auth.config.js file, in the servers.oauth2 key. Note that this is NOT the same as the sources.example_oauth key.

oauth2: {
    enable: env('OAUTH2_SERVER_ENABLE', false),

    // Grants that are available to clients. Supported types are authorization_code, password
    grants: ['authorization_code'],

    // Built in data retrieval endpoints. These are protected by user-specific OAuth2 tokens
    built_in_endpoints: {

        // Get the token user's data
        user: {
            enable: env('OAUTH2_SERVER_ENABLE', true),

            // Fields to return to the endpoint
            // The keys are the keys in the request. The values are the keys in the user.
            fields: {
                username: 'uid',
                id: 'uuid',

                // Data is a special key. It's key-value pairs are included,
                // unserialized, from the user's JSON data.
                data: {
                    // Fields stored in serialized data can be included here:
                    // special_field: 'some_json_data_field',
                },
            },
        },
    },
},

Here we see a relatively straightforward implementation for the OAuth2 server. Let's walk through the configuration options in turn:

OAuth2 Server Options

enable (default: false)

Set to true to allow client applications to authenticate with your application using the OAuth2 server.

grants (default: ['authorization_code'])

An array of the enabled grant types. As of now, the authorization_code is the only supported grant.

built_in_endpoints

An object specifying the configuration for various built-in API endpoints for OAuth2 authentication.

built_in_endpoints.user

This endpoint provides information about the user associated with the provided bearer token.

built_in_endpoints.user.enable

Set to true to enable this endpoint.

built_in_endpoints.user.fields

An object mapping fields sent in the response to fields on the module:flitter-auth/model/User~BaseUser model.

built_in_endpoints.user.fields.data

This is a special field. Any mappings here will be looked up from the User's serialized JSON and sent as unserialized values.

Client IDs and Client Secrets

By default, Flitter Auth provides no interface for generating client IDs and client secrets for applications to use with this server. However, it's a fairly straightforward process. Here's how to do it from the Flitter Shell:

> Client = _services.models.get('auth::Oauth2Client')
> client = new Client({ name: 'Some Application', grants: ['authorization_code'], redirectUris: ['http://an.array.of/valid/redirect/uris'] })
> await client.save()
> client.clientID // 'fa6bd14a-e643-403c-81c0-af73ec19860d'
> client.clientSecret // '0865a4de-7b4e-438b-a20b-cb326459d5ee'

Bearer Token Middleware

You can protect routes to be accessible only by valid bearer tokens by applying the auth:Oauth2TokenOnly middleware to the route. This will inject some user info in the req.user element, which you can then use to query the whole user object. (See: module:flitter-auth/middleware/Oauth2TokenOnly~Oauth2TokenOnly)

Authentication API

When an external application authenticates against your app via Flitter-Auth's OAuth2 server, it will need to redirect the users to your application's OAuth2 authorization URL with the appropriate info. Here are some important formats:

User Authorization

This is where users are redirected when they click the "Sign-In with YourApp" button. It takes the following format:

https://your.app.url/auth/service/oauth2/authorize?client_id=<client_id>&redirect_uri=<redirect_uri>

Where <client_id> is the value of the clientID of the application's module:flitter-auth/model/Oauth2Client~Oauth2Client instance and <redirect_uri> is the place the user will be redirected when the authentication is successful.

<redirect_uri> must be one of the values in the redirectUris array of the module:flitter-auth/model/Oauth2Client~Oauth2Client instance.

Auth Code Redemption

Once the user auth is complete, the user will be sent back to the redirect_uri provided. When they are sent back, an authorization code will be appended to the URL query string, like so:

https://external.app.url/oauth2/callback?code=XYZ

Your application can now redeem this authorization code for a full OAuth2 bearer token on the user's behalf. This token can be used to fetch information about the user from the API. To do this, your application should make a POST request to the endpoint with the following fields in the request body:

https://your.app.url/auth/service/oauth2/redeem

  • code - the authorization code generated when the user was authorized
  • client_id - the application's clientID
  • client_secret - the application's clientSecret
  • grant_type - the grant type (only one is supported, so this value should always be authorization_code)

The server will respond with the bearer token in the access_token field.

Built-In User API

Flitter Auth's OAuth2 server comes with a simple built-in API for accessing user data using a bearer token, as detailed above. Obviously, for more complex applications, you can disable this and implement it yourself. However, the basic endpoint is useful for getting basic OAuth2 working with your app. This API endpoint is accessible at:

https://you.app.url/auth/service/oauth2/data/user

To authenticate with the bearer token, provide the following header:

Authorization: Bearer <token>

Where <token> is the bearer token redeemed when the user signed-in.