FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects

Activate Account

This repository hosts the API for the Activate Account service, which manages the signup and account activation processes as part of the transition away from the legacy Raven Login system. The API enables integration with a new web application designed to streamline user registration and initial account setup.

Documentation

The project has detailed documentation for developers, including a "getting started" guide. See below for information on building the documentation.

Guidebook - Quickstart and Testing

To know how to get started with this project visit our Guidebook.

To view notes on how to get the project working locally visit the getting started section of the Guidebook.

To get started with Testing visit our testing section of the Guidebook.

Loading secrets at runtime

If the EXTRA_SETTINGS_URLS environment variable is non-empty it is interpreted as a comma-separated set of URLs from which to fetch settings. Settings are fetched and applied in the order they are listed.

The settings should be in the form of a YAML document which is fetched, parsed and interpolated into the Django settings when the server starts.

EXTRA_SETTINGS_URLS currently understands the following URL schemes:

  • file://... URLs are loaded from the local file system. If the URL lacks any scheme, it is assumed to be a file URL.
  • https://... URLs are fetched using HTTP over TLS.
  • gs://BUCKET/LOCATION formatted URLs specify a Google Cloud Storage bucket and a location within that bucket of an object to load settings from.
  • sm://PROJECT/SECRET#VERSION formatted URLs specify a Google Secret Manager secret to load settings from. If the version is omitted, the latest version is used.

For Google Cloud Storage and Secret Manager URLs, application default credentials are used to authenticate to Google.

Settings which can be loaded from external YAML documents can also be specified in environment variables. A variable of the form EXTERNAL_SETTING_[NAME] is imported as the setting "NAME" and the value of the variable is interpreted as a YAML formatted value for the setting.

Notes on debugging

The Full-screen console debugger pudb has been included to allow you to run a debug in the docker-compose environment. To use, simply set the breakpoint using import pdb; pdb.set_trace() and attach to the container using:

docker attach activate_account_development_app_1

For a fuller description of how to debug follow the guide to debugging with pdb and Docker (it works just as well for pudb).

CI configuration

The project is configured with Gitlab AutoDevOps via Gitlab CI using the .gitlab-ci.yml file.

Session authentication

In order to leverage existing tooling for OAuth2, it was decided that retrieving the access token and handling authentication would follow the OAuth2 specification. This means we have an API endpoint available on /token/ that accepts a application/x-www-form-urlencoded encoded document POST-ed to it with the following fields:

  • grant_type - must be urn:devops.uis.cam.ac.uk:params:oauth:grant-type:new-user-credentials
  • crsid - must be the CRSid as a string
  • date_of_birth - must be a RFC 3339 formatted date. E.g. 1996-12-19. No time-portion is accepted.
  • last_name - must be a string
  • code - must be a string

Either crsid or last_name must be provided, but not both.

An example request would be (line breaks added for display purposes):

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Adevops.uis.cam.ac.uk%3Aparams%3Aoauth%3Agrant-type
%3Anew-user-credentials&date_of_birth=1996-12-19&last_name=Smith&co
de=ABCDEF12345

If grant_type is anything other than what we expect, we respond with a 400 response as per the spec with the following content:

{
  "error": "unsupported_grant_type"
}

If the user credentials are missing a required field, e.g. no code when it is required, we respond with a 400 response and:

{
  "error": "invalid_request"
}

If the all the required user credentials are provided but they do not match a known user, we respond with a 400 response and the following document:

{
  "error": "invalid_grant"
}

If all goes well, we return a RFC 6749 compliant JSON document response. The access_token field is the newly minted token, the token_type field must be bearer and the expires_in field gives the lifetime of the token in seconds. An example response:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"abcdefg1234567",
  "token_type":"bearer",
  "expires_in":3600,
}

To authenticate to other API endpoints, we would set the following header: Authorization: Bearer abcdefg1234567.

Generating the OpenAPI Specification

To generate the OpenAPI specification for this project, you can use the configured Poetry task. Run the following command:

poetry poe generate-schema

This command utilizes the poe task generate-schema to build and run the necessary Docker commands, generating the openapi.yaml file which contains the OpenAPI schema for the API.

Copyright License

See the LICENSE file for details.