Updated: 2019-01-22

Frontier Auth Service

The Frontier Auth service is a OAuth2 provider for third-party developers to use in applications that require access to Frontier APIs.

The Auth Service uses the standard OAuth2 specification (https://oauth.net/2/). It currently only allows Authorization Token authentication.

The access token returned by from the Auth Service has a short expiry time and a refresh token which can be used when the access token has expired. Note: The refresh token will be updated each time a new access token is requested. The refresh token may also expire, in which case you will need to direct users to re-authorize using the Frontier Auth Service.

We also support PKCE (Pronounced Pixie). Which allows logins from client side applications. See Execute an Authorization Code Grant Flow with PKCE for details.

FAQ

What is Personally Identifiable Information for Frontier Games?

  • Player real life names and email addresses
  • In-game identities, such as Commander Names, Gamertags, Steam Nicknames, Online IDs etc.

Who is responsible for accepting Frontier Terms & Conditions?

  • For members of open source projects, this is the person who obtains an API key from the Frontier Auth service and configures an instance of that project to use it when that project is running as a service.
  • If anybody else runs an instance of your project, then they will need to obtain their own API key.
  • This means your API key SHOULD NOT be included in your open source code.

Why do we start needing to consider Personally Identifiable Information?

  • Some games store PII individually, such as in Elite Dangerous' journal files. Those are considered local storage and under the control of their player, per the Frontier Privacy Policy.
  • API services offer access to many players' information, so a separate consent step is required, as such you will have to notify players what information you will be using and why.

Example Implementation

The PHP example below is an example of using the Frontier Auth Service with the popular League OAuth2 package: (https://github.com/thephpleague/oauth2-client)

Notes:

  • Any OAuth2 client can be used for your particular platform.
  • Do not send the client secret directly from a user's browser i.e. browser side javascript), always use a server side call to get the user's access token.
  • The access token is a Bearer token used in the Authorization header. i.e. Authorization: Bearer <token>
  • The access token is a JWE (JSON Web Encryption) JWT (JSON Web Token).
  • Use your selected OAuth2 client to retrieve the resource owner details.
  • Any authorisation/authentication errors will also come back to your callback URL as per spec.
  • The User Details will contain Frontier ID, email address, other account information and information about linked accounts.
  • You will also get any details a third party service provides such as Xbox Live, Steam or Playstation Network should the user have logged in via that service.
  • Refreshed tokens may omit any third party details.

PKCE Notes:

  • If you are using PKCE please note you will need to make sure your sha256 hash of the verfier is a binary data digest, and not hex encoded - as implementations may vary - and, then encoded using Base64URL Encoding.
  • Your code_verifier must be URL safe, so ideally you'd generate some random bytes, and Base64URLEncode that as your verifier, then for the code_challenge you would sha256 to a binary data representation, then Base64URLEncode that as per the specification.
  • If you are using a library other than in the Auth0 example, you must make sure the output would be the same as in the example.


Audience

You may add an audience query string parameter to the /auth route, i.e. ?audience=xbox or a combination using comma seperated strings ?audience=xbox,steam,frontier

available audiences (lower case please):

  • xbox - Microsoft Xbox Live
  • psn - Playstation Network
  • steam - Steam
  • frontier - Frontierstore.net login
  • all - All of the above (default)

Scopes

You should also pass a scope to the auth service /auth endpoint when first requesting access, query parameter is scope, scopes are space seperated as per OAuth2 spec, and are additive.

Available scopes:

  • auth (default) - User's email, firstname, lastname, thirdpartyuserID (if logged in via third party) and platform.
  • capi - Access to user's Companion API information

Example Factory - Symfony

<?php

declare(strict_types=1);

/*
 * MIT Licence
 *
 * Copyright 2018 Frontier Developments plc
 *
 * Permission is hereby granted, free of charge, to
 * any person obtaining a copy of this software and
 * associated documentation files (the "Software"),
 * to deal in the Software without restriction,
 * including without limitation the rights to
 * use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is
 * furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission
 * notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
 * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE
 * OR OTHER DEALINGS IN THE SOFTWARE.
 */

namespace App\Factory;

use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\GenericProvider;

/**
 * Creates a League OAuth2 GenericProvider with the correct
 * credentials for using the Frontier Auth service.
 */
class AuthProviderFactory
{
    private const CLIENT_ID = 'foo';

    private const CLIENT_SECRET = 'bar';

    private const AUTH_API = 'https://auth.frontierstore.net';

    private const CALLBACK_URL = 'https://myclient.example/auth';

    /**
     * @return GenericProvider
     */
    public function create(): AbstractProvider
    {
        return new GenericProvider([
            'scope' => 'auth capi',
            'clientId' => self::CLIENT_ID,
            'clientSecret' => self::CLIENT_SECRET,
            'redirectUri' => self::CALLBACK_URL,
            'urlAuthorize' => self::AUTH_API . '/auth',
            'urlAccessToken' => self::AUTH_API . '/token',
            'urlResourceOwnerDetails' => self::AUTH_API . '/decode', // You may also use /me if you don't need the full JWT expiry, etc.
        ]);
    }
}

Example user information from /me route using auth or capi scope(JSON formatted):

PC login

{
    "customer_id":"12345789",
    "firstname":"Dave",
    "lastname":"Lister",
    "email":"dave@reddwarf.ship",
    "platform":"frontier",
    "thirdPartyUserId": null,
    "parent_id": null
}           

PSN login (auth or capi scope, JSON format):

{
    "customer_id":"987654321",
    "firstname":"PSNUser",
    "lastname":"",
    "email":"1234567890@frontier-playstation.co.uk",
    "parent_id":"12345789",
    "thirdPartyUserId":"1234567890",
    "platform":"psn"
}

Example /decode route return information

"iat" and "exp" claims are UTC timestamps. "iss" will always be "https://auth.frontierstore.net"

{
  "iss":"https://auth.frontierstore.net"
  "usr": {
    "customer_id": "123456890"
    "firstname": "Dave"
    "lastname": "Lister"
    "email": "dave@example.com"
    "platform": "frontier"
  },
  "iat": 1547463135
  "exp": 1547477535
  "scope": "auth capi"
}