Skip to content

2.3: Single JWT

Sebastian Schendel edited this page Dec 29, 2020 · 2 revisions

Recommended for external server-calls

If you want to access your api from an external server, to which you have full control to, you can use the single JWT authentication. It is important to consider, that anyone, that knows an authentication-key, can legitimately authenticate to your endpoints. I would recommend to use this method only, if you can store the key securely and nobody but you can see it.

In the configuration-view of your application you have to choose a "Token Secret". This secret is used to sign the JWT-tokens. It must not get leaked to anywhere else because everyone with this key could generate their own tokens - that means universal access to all endpoints of this application.

A random token secret with a reasonable length of 52 characters will be prefilled in a newly created application. But of course you have the possibility to change it to a custom value.

Let us now turn to the request. I will demonstrate it with simple Angular-code examples, but you surely can do the same thing in any other programming language as well. To get a jwt-token, that legitimates your further requests, you simply have to login with a valid username/password combination:

// Example with username/pass as a basic-authorisation header (recommended):
this.httpClient.post('https://my-website.dev/api/auth', undefined, {
  'x-api-key': 'ytaaYCMkUmouZawYMvJN9',
  'authorization': 'Basic ' + btoa(username + ':' + pass),
});

// Alternatively you can send username/pass in the request-body:
this.httpClient.post(
  'https://my-website.dev/api/auth',
  JSON.stringify({
    username: username,
    password: pass,
  }),
  {
    'x-api-key': 'ytaaYCMkUmouZawYMvJN9',
  }
);

The resulting JSON response contains your token and the name of the authenticated user:

{
  "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJteS13ZWJzaXRlLmxvY2FsIiwiYXVkIjo0LCJzdWIiOjQxLCJpYXQiOjE1OTQ3NDk2OTUsIm5iZiI6MTU5NDc0OTY5NSwianRpIjoiSjdjTldsM3J0Q3VRSUN3azA2YW9LIiwiZXhwIjoxNTk3MzQxNjk1LCJzaWQiOiIxNDJhZmVhZG9jOTIybzJzZWJpaDciLCJzaWRfY2hhbGxlbmdlIjoiYmwwMzQyYXNpS0JIVS81a0g0Q0xWWGNzYWlNMTExOCJ9.9y4h0nslg2JHLSPFevOK-JWx2P_RfaaqSHRPi7nnSMk",
  "username": "sebi"
}

If you are interested in the data which is included in the token, you can easily decode it (for example online under https://jwt.io). The data is signed, so it cannot be changed without knowing the server's secret. A token that is generated from my AppApi-module contains the following data:

{
  "iss": "my-website.local", // issuer-claim: your domain
  "aud": 4, // audition-claim: the internal ID of your application
  "sub": 41, // subject-claim: userID of the authenticated user
  "iat": 1594749695, // issued-at-claim: creation-time
  "nbf": 1594749695, // not-before-claim: creation-time
  "jti": "J7cNWl3rtCuQICwk06aoK", // JWT-ID: unique id
  "exp": 1597341695, // expires-claim: token-expiration-timestamp
  "sid": "142afeadoc922o2sebih7", // Session-ID of the linked processwire-session
  "sid_challenge": "bl0342asiKBlU/5kH4CLVXcsaiM1118" // sid-challenge of the linked processwire-session
}

Every claim of an incoming token will be validated. If anything doesn't match, the token will be revoked.

With this functioning token you can now make authenticated requests! You only have to add it as a Bearer-authentication header:

this.httpClient.get('https://my-website.dev/api/auth', {
  'x-api-key': 'ytaaYCMkUmouZawYMvJN9',
  'authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJteS13ZWJzaXRlLmxvY2FsIiwiYXVkIjo0LCJzdWIiOjQxLCJpYXQiOjE1OTQ3NDk2OTUsIm5iZiI6MTU5NDc0OTY5NSwianRpIjoiSjdjTldsM3J0Q3VRSUN3azA2YW9LIiwiZXhwIjoxNTk3MzQxNjk1LCJzaWQiOiIxNDJhZmVhZG9jOTIybzJzZWJpaDciLCJzaWRfY2hhbGxlbmdlIjoiYmwwMzQyYXNpS0JIVS81a0g0Q0xWWGNzYWlNMTExOCJ9.9y4h0nslg2JHLSPFevOK-JWx2P_RfaaqSHRPi7nnSMk',
});

This request proves, that I am now authenticated:

{
  "id": 41,
  "name": "sebi",
  "loggedIn": true
}

Without the authorization-header, I would only be a not-authenticated guest:

{
  "id": 40,
  "name": "guest",
  "loggedIn": false
}

Wow! It works!


➡️ Continue with 2.4: Double JWT
⬅️ Back to 2.2: PHP-Session