3. Consumer API Authorization¶
Some API endpoints require authorization. Only users with a third party account (e.g. Google or Facebook) are granted access. Such accounts cannot be set up without some human interaction. The requirement for user authentication guards against bots filling the wsbackend database with rubbish.
The websensor Web Application uses the Open ID Connect (OIDC) protocol to communicate with a third-party identity provider (IdP). When a user authenticates, the IdP produces an access token. This token is unique to a user and decodes to a number of claims. These include:
User name.
Audience (URL of the websensor API for which access has been granted).
Issuer (URL of the identity provider).
Issued timestamp.
Expiry timestamp.
Scope (granular API permissions).
Tokens are not encrypted. They must always be transmitted through a secure channel (HTTPS). The value of tokens is they include a digital signature. If signature verification is successful then the claims can be trusted. In this way access tokens are used to access protected API resources.
The access token also grants the Web Application permission to read some personal data about
a user (e.g. name and profile picture). Crucially these data are not stored in the Web Application itself.
They are requested by making an
API call to /userinfo
API endpoint of the IdP. It can be assumed that the IdP handles these data
in a secure and GDPR compliant way.
3.1. Production¶
In a production environment, the IdP is Auth0.com. Others can be used if they adhere to the OIDC protocol.
Auth0.com acts as an intermediary. It allows users to authenticate with a large number of OAuth2 providers such as Google, GitHub and Facebook.
3.1.1. Obtain an API Access Token¶
wsfrontend obtains an access token fom the identify provider using the Authorization Code Grant Flow.
3.1.2. Protected API Resource is Called¶
wsfrontend calls wsbackend endpoints with the access token:
curl -X GET "{WSB_HOST}:{WSB_PORT}/api/consumer/v1/me" -H "accept: application/json" -H "Authorization: Bearer eyJhbGciOiJS... ZOA4t7Q"
3.1.3. Access Token is Validated¶
The access token signature is generated asymetrically (RS-256). A private key (on Auth0.com) generates the signature. A public key (hosted by Auth0.com) is used for validation.
wsbackend downloads the public_key
(JWKs) from Auth0.com:
GET {IDP_ORIGIN}{IDP_JWKS} => GET https://plotsensor.eu.auth0.com/.well-known/jwks.json
Signature verification and decoding are performed using PyJWT:
decoded = jwt.decode(
token,
public_key,
algorithms=self.algorithms,
audience={API_AUDIENCE},
issuer={IDP_ORIGIN}
)
If validation fails, an exception is raised. The token is rejected and the API
responds with an error 403: Forbidden
.
3.1.4. Protected Resource Content are Served¶
If validation succeeds, wsbackend transmits a 200 OK
response to the wsfrontend, along with the requested resource data.
3.2. Testing¶
For test, the OIDC provider is substituted with a mock https://www.npmjs.com/package/oauth2-mock-server. The test workflow
sets this up first on http://127.0.0.1:3000
.
3.2.1. Obtain an API Access Token¶
Access tokens are obtained from this using the client-creditials OAuth2 flow.
3.2.2. Test Scripts Call Protected API Resources¶
wsbackend endpoints are called with the access token in the HTTP header.
3.2.3. Access Token Validated¶
wsbackend downloads a public_key
from the mock provider JWKs endpoint. from the mock provider on port 3000:
GET {IDP_ORIGIN}{IDP_JWKS} => GET http://127.0.0.1:3000/jwks
Userinfo can also be mocked up.