Authenticating with the API Server

This document describes how an application can request an access token from Apcera's auth server for making calls to the Apcera REST API.

Overview

Creating an application that integrates with Apcera's API server involves the following steps:

  1. Define policy that indicates when Apcera's auth server should issue a token to the application.
  2. Request an API token from the Apcera auth server.
  3. Make API calls using the token.

Depending on the type of authentication mechanism being used, your application may request a token by calling the POST /v1/oauth2/token endpoint, passing the user's credentials in the request. If your application is authenticating against an identity provider (such as Google OAuth2 for Devices), the process involves making a sequence of calls to obtain an access token, as illustrated below.

screenshot

Defining authentication policy

The Apcera authentication server must be able to parse and validate credentials in order to issue an access token to the requesting application. If the application is autonomous and acting on its own behalf, we recommend using Google's OAuth2 for Devices. Create policy that defines if and when the Apcera auth server should respond to token requests that contain an authentication statement issued by Google. The following policy instructs the Apcera auth server to issue a token if the requester can produce a token issued by Google that contains the "example.com" Google email address domain:

on auth::/oauth2/http {
    if (Google->email endsWith "@example.com") {
        permit issue
        name Google->email
    }
}

Authentication API hosts

Each authentication mechanism (LDAP, Google OAuth, Crowd and so forth) configured on an Apcera cluster has a dedicated API host against which you make authentication API requests. Depending on which authentication mechanisms are available on your cluster, one or more of the following authentication host endpoints are available:

  • basicauth.<domain> – For basic (username, password) authentication
  • crowdauth.<domain> – For Atlassian Crowd authentication
  • gauth.<domain> – For Google Oauth2 and device-flow authentication
  • kerberosauth.<domain> – For Kerberos authentication
  • ldapauth.<domain> – For LDAP authentication with basic (username, password) credentials

For example, assuming the cluster at example.com is configured to use basic authentication you would make authentication API calls to the host at basicauth.example.com:

POST /v1/oauth2/token HTTP/1.1
Host: basicauth.example.com
Authorization: Basic <base64-encoding of 'username:password'>

Note: To encode a user:password pair with base64 encoding, you can use the following command:

echo -n "ldapuser:ldappassword" | base64

Prior to the Q1 2016 Apcera Platform release, there was a single authentication API host at auth.<domain> that handled all authentication calls. You include a grant_type field in the request body that indicates the authentication mechanism to use. The grant_type field may be assigned one of the following values:

  • basic — Basic authentication.
  • ldap_basic — LDAP (basic)
  • crowd — Atlassian Crowd
  • kerberos_v5 — Active Directory

For example, the following is functionally equivalent to the previous example except that it uses the auth.<cluster> API host rather than ldapauth.example.com, and includes grant_type=ldap_basic in the request body:

POST /v1/oauth2/token HTTP/1.1
Host: auth.example.com
Authorization: Basic <base64-encoding of 'username:password'>
Content-Type: application/x-www-form-urlencoded

grant_type=basic

Note: The auth.<domain> API host is available in the Q1 2016 Apcera Platform release but will eventually be deprecated. Developers are encouraged to use the authentication-specific hosts (gauth.<domain>, for example).

Requesting a token

An authenticating client requests an Apcera access token by calling the POST /v1/oauth2/token endpoint on the appropriate host. If you are using Google as your identity provider you use a different set of endpoints to authenticate the user (see Google OAuth2 Device Flow).

For example, the following request obtains an access token using LDAP (basic) authentication:

POST /v1/oauth2/token HTTP/1.1
Host: ldapauth.example.com
Authorization: Basic <base64-encoding of 'ldap-username:ldap-password'>
Content-Type: application/x-www-form-urlencoded

A successful response is shown below:

HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: userinfo=eyJwcm9maWxlIjoiIiwibm...; Path=/; Domain=ldapauth.example.com; Expires=Sat, 14 Nov 2015 18:34:05 UTC
Set-Cookie: token=eyJ0eXAiOiIiLC...; Path=/; Domain=ldapauth.example.com; Expires=Sat, 14 Nov 2015 18:34:05 UTC

{
    "access_token": "eyJ0eXAiOiIiLC...",
    "expires_in": "86400",
    "token_type": "JWT"
}

Note the following about the response to POST /v1/oauth2/token:

  • Use the access_token field in the response body to authenticate calls API calls (see Calling an API).
  • The expires_in response body field indicates the number of seconds until the token expires.
  • The token_type field is set to JWT (JSON Web Token).
  • The response header contains the following cookies:
    • token, which contains the same authentication token in the response body
    • userinfo, which holds a Base64-encoded JSON string containing information about the user who logged in.

Google OAuth2 Device Flow

The following steps describe how to use Google OAuth2 Device Flow to obtain a Google refresh token and exchange it for an Apcera access token. This requires that Google authentication be enabled on the target cluster, and that policy is defined to permit the Auth server to issue a token for the authenticating user (see Defining authentication policy).

To obtain an access token using Google OAuth Device Flow:

  1. Request a Google code (GET /v1/oauth2/device/google/getcode):

    Request

     GET /v1/oauth2/device/google/getcode?scope=email
     Host: gauth.example.com\    
    

    Response body

     HTTP/1.1 200 OK
     Content-Type: application/json    
     {
       "device_code": "FGMJ-VXQK4/i1OZWGp8wuk6NY0HU_h9anl24IVJySvy0GOypjHgUsc",
       "user_code": "FGMJ-VXQK",
       "verification_url": "https://www.google.com/device",
       "expires_in": 1800,
       "interval": 5,
       "error": ""
     }
    

    Note: This example uses the gauth.<domain> authentication API host made available in the Q1 2016 Apcera Platform then you must also add grant_type=google_device to the URL (GET /v1/oauth2/device/google/getcode?grant_type=google_device&scope=email). See Authentication API hosts.

  2. Open the verification URL (verification_url) in a web browser and provide the user code (user_code) from the response in the Google form.
  3. Redeem the code by calling the POST /v1/oauth2/device/google/redeemed API:

    Request

     POST /v1/oauth2/device/google/redeemed
     Host: gauth.example.com
     Content-Type: application/json
    
     {
         "device_code": "FGMJ-VXQK4/i1OZWGp8wuk6NY0HU_h9anl24IVJySvy0GOypjHgUsc"
     }
    

    Response

     HTTP/1.1 200 OK
     Content-Type: application/json
    
     {
         "refresh_token": "1/lGpgaCZHMCtO28LdK6blAztHdzsoSi6Zpu9V-zpGuME",
         "token_type": "GOOGLE_REFRESH"
     }
    
  4. Exchange the Google refresh token for an Apcera access token by calling the POST /v1/oauth2/device/google/refresh API:

    Request:

     POST /v1/oauth2/device/google/refresh
     Host: gauth.example.com
    
     {
         "refresh_token": "1/lGpgaCZHMCtO28LdK6blAztHdzsoSi6Zpu9V-zpGuME",
         "token_type": "GOOGLE_REFRESH"
     }
    

    Response

     HTTP/1.1 200 OK
     Content-Type: application/json
     Set-Cookie: userinfo=eyJwcm9maWxlIjoiaHR0... ; Path=/; Domain=gauth.example.com; Expires=Wed, 11 Nov 2015 17:29:10 UTC
     Set-Cookie: token=eyJ0eXAiOiIiLCJhbGciOiIifQ...; Path=/; Domain=gauth.example.com; Expires=Wed, 11 Nov 2015 17:29:10 UTC
     Vary: Accept-Encoding
    
     {
         "access_token": "eyJ0eXAiOiIiLCJhbGciOiIifQ...",
         "expires_in": "86400",
         "token_type": "JWT"
     }
    

    The access_token field contains the token you can use to authenticate API calls.

Calling an Apcera API

To call an Apcera REST API, simply add the access token to the Authorization header with the preamble Bearer. For example, the following makes a request to GET /v1/info.

GET /v1/info HTTP/1.1
Authorization: Bearer eyJ0eXAiOiIiLCJhbGciOiIifQ...
Host: api.example.com

Response:

{
  "name": "try",
  "url": "http://api.try.apcera.net/",
  "cluster_domain": "apcera.me"
}