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 beurn: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.