Teaching vacancies - Jobseekers Authentication
Jobseekers authenticate via the GOV.UK One Login service.
For detailed information, check the GOV.UK One Login tech documentation
GOV.UK One Login configuration
Environments
Different environments talk to different GOV.UK One Login environments:
-
Local development -> Integration GOV.UK One Login
-
QA -> Integration GOV.UK One Login
-
Staging -> Integration GOV.UK One Login
-
Production -> Production Integration GOV.UK One Login
-
Review Apps: Due to the ephemereal nature of these environments, they cannot be automatically configured to connect with GOV.UK One Login. They use a magic link sent via email to authenticate.
Configuring GOV.UK One Login environments
Integration
The GOV.UK One Login integration environment can be managed through their admin tool account (registration and access).
Limitation: the integration environment account can only belong to a single user who set it up. To change it, a different developer needs to set it up froms scratch with their own account or ask for support request so the configuration can be requested/transfered.
Production
At the moment, there is no admin portal where we can configure the production integration at. The production environment is set up by their technical team and managed through support requests.
Support
The GOV.UK OneLogin team has Slack channel:
- You will need to create an account in UK Government Digital(
ukgovernmentdigital.slack.com
) using your@education.gov.uk
email address) - Their channel within the space is
#govuk-one-login
. - Alternative there is a contact form.
For support, we will need to provide the Client ID we need help with.
Set environment variables
Each environment will need these values to be set on AWS Parameter Store secrets under /teaching-vacancies/*env*/app/secrets
.
RAILS_MASTER_KEY=
GOVUK_ONE_LOGIN_CLIENT_ID=
GOVUK_ONE_LOGIN_BASE_URL=
Secrets containing GOV.UK One Login public/private keys
The Rails master key is used to automatically read the Rails Secrets encrypted file: config/secrets.yml.enc
, following the
Rails custom credentials guidance.
The credentials file contains the one_login.public_key
and one_login.private_key
values, needed for each GOV.UK One Login
integration configuration.
- To access/edit this file, run
bin/rails credentials:edit
. - To access the credentials within the app:
Rails.application.credentials.one_login.private_key
GOV.UK One Login contingency fallback playbook
Background
This is a contingency plan for when GOV.UK One Login has an outage. The fallback authentication method relies on the email address we have stored in DB for the Jobseekers.
It replaces the GOV.UK One Login sign in method with one whereby the user is prompted to enter their email address, and clicks a unique login link. This login link works only once and expires after a configurable time.
How to use
Here are the steps to follow to use our contingency fallback sign-in method.
First, decide whether to switch on the fallback authentication. This call should be made by the Product Owner/Manager if they are available.
Toggle Authentication Fallback
- Switch on the fallback authentication by setting the environment variable
AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS
totrue
. - Switch off the fallback authentication by setting the environment variable
AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS
tofalse
.
Toggling Authentication Fallback Using an automated deployment
Changing the environment variable within the <env>_app_env.yml
follows the standard deployment procedure, and allows deployments to production to continue:
- create a feature branch
- edit the file terraform/workspace-variables/production_app_env.yml
- set the environment variable
AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS
totrue
orfalse
as required - create a Pull Request
- merge after approval
Toggling Authentication Fallback Using manual steps
The following method is included for completeness, but should be considered as a "panic mode" option only.
It requires SpaceDeveloper
permission on the s189-teacher-services-cloud-production
subscription, and only persists until the next Automated Deployment to staging and production
-
Block all deployments to
production
by requesting in the Slack channel#tv_devs
-
Log in in the Azure Portal and request access to the
s189-Contributor and Key Vault editor
role in thes189-teacher-services-cloud-production
subscription. -
Once having the access granted by one of the managers, login into Azure from the console:
az login --tenant 9c7d9dd3-840c-4b3f-818e-552865082e16
-
Get the credentials for the production cluster:
make production get-cluster-credentials CONFIRM_PRODUCTION=YES
-
Get the current environment value:
kubectl -n tv-production exec deployment/teaching-vacancies-production -- env | grep AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS
-
Get current environment variable value over one of the listed pods:
-
Update the environment variable with the set env command
-
Enable the fallback with:
kubectl -n tv-production set env deployment/teaching-vacancies-production AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS=true
-
Wait for a bit until the pods get automatically restarted with the new value. Check that the value changed:
kubectl -n tv-production exec deployment/teaching-vacancies-production -- env | grep AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS
-
When not needed anymore disable the fallback with:
kubectl -n tv-production set env deployment/teaching-vacancies-production AUTHENTICATION_FALLBACK_FOR_JOBSEEKERS=false
GOV.UK One Login flow
The basic flow for a Jobseeker using our service is as follows:
- When a jobseeker needs to sign-in/sign-up, they get sent to a Teaching Vacancies sign-in page pointing to GOV.UK One Login.
- After confirmation, they get redirected to the GOV.UK One Login service.
- On GOV.UK One Login the jobseeker either:
- register a new account.
- sign-in with their existing One Login account.
- After a successfull sign-in, they get redirected back to Teaching Vacancies.
- Teaching Vacancies matches/creates the internal Jobseeker associated with the GOV.UK One Login account, and signs-in the Jobseeker session.
The detailed flow of requests/responses between Teaching Vacancies and GOV.UK One Login can be found in the tech documentation
Implementation in Teaching Vacancies
The Jobseeker session is still managed by Devise gem.
Teaching Vacancies configures OneLogin as an Omniauth provider through the Devise Omniauth configuration.
There are a few paths in our service related with GOV.UK One Login:
-
/jobseekers/sign-in
--> Bridge page in our service that, upon confirmation, sends the non-signed jobseeker to sign through GOV.UK One Login. -
/jobseekers/auth/govuk_one_login/callback
--> GOV.UK One Login redirects jobseekers back to this path after signing-up/in through their service. All the heavy lifting in our side is done here. -
/jobseekers/sign_out
--> Signs the jobseeker out from our service. GOV.UK One Login redirects jobseekers back to this path after signing users out in their service.
How do we map the GOV.UK One Login user with our service jobseekers
When a successfully authenticated GOV.UK One Login user gets redirected back to our service. This user information contains:
- The user id in GOV.UK One Login
- The email address for this user in GOV.UK One Login
With this information, Teaching Vacancies will match/create/update a Jobseeker account within our service, and sign them in.
The flow
The Jobseeker sign-up/in flow can we break these phases:
- User gets sent to GOV.UK One Login for authentication.
- Validate and get user info from the GOV.UK One Login response.
- Set the Teaching Vacancies Jobseeker user.
- User gets redirected to the right page in Teaching Vacancies.
The 3 first phases flows are as follows:
1. User gets sent to GOV.UK One Login for authentication
block-beta
columns 3
Start["Sign-in/up button or action that\nrequires user to be signed in"] space:2
space:3
SignIn["Sign-in page pointing to\nGOV.UK One Login"] space SetSession["Set 'state' and 'nonce'\nin users session"]
space:3
Click["User confirms Sign-in attempt"] space:2
space:3
OneLogin["User redirected to\nGOV.UK One Login for authorization"] space
Start --> SignIn
SetSession -- "On page load" --> SignIn
SignIn --> Click
Click --> OneLogin
2. Validate and get user info from the GOV.UK One Login response
block-beta
columns 8
OneLogin["GOV.UK\nOne Login"] space
block:TeachingVacancies:6
columns 2
RedirectionEndpoint(("OneLogin\nredirection\nendpoint")) space
ValidSession{"Valid user\nsession?"} space
ValidResponse{"Valid\nresponse?"} space
NeedsToken(("Needs\ntoken")) space
ValidToken{"Valid\ntoken?"} Error["Error page"]
ValidIdToken{"Valid\nid token?"} space
NeedsUserInfo(("Needs\nuser info")) space
ValidUserInfo{"Valid\nuser info?"} space
SetUser(("set\nJobseeker\nuser"))
classDef start fill:#90ee90;
classDef end fill:#fa8072;
classDef error fill:#e60026;
class RedirectionEndpoint start
class SetUser end
class Error error
end
OneLogin -- "Auth response\nredirection" --> RedirectionEndpoint
RedirectionEndpoint --> ValidSession
ValidSession -- "No" --> Error
ValidSession -- "Yes" --> ValidResponse
ValidResponse -- "No" --> Error
ValidResponse --> NeedsToken
NeedsToken -- "Requests Token" --> OneLogin
NeedsToken --> ValidToken
ValidToken -- "Yes" --> ValidIdToken
ValidToken -- "No" --> Error
ValidIdToken -- "Yes" --> NeedsUserInfo
ValidIdToken -- "No" --> Error
NeedsUserInfo -- "Requests\nUser info" --> OneLogin
NeedsUserInfo --> ValidUserInfo
ValidUserInfo -- "No" --> Error
ValidUserInfo -- "Yes" --> SetUser
3. Set the Teaching Vacancies Jobseeker user
block-beta
columns 3
OneLoginUserInfo(("OneLogin\nuser info")) space:2
FindJobseeker["Find Jobseeker\n(first by One Login id,\nif not by email)"] space:2
ExistingJobseeker{"Jobseeker\nfound?"} CreateJobseeker["Create Jobseeker using\nOne Login email and id"] space
FirstTime{"First time\nusing\nOne Login"} SetJobseekerId["Set GOV.UK One Login ID on\nthe Jobseeker\n(links the account)"] RedirectJobseeker2(("Redirect\nJobseeker"))
EmailChanged{"Email\nchanged in\nOne Login"} UpdateJobseekerEmail["Updates Jobseeker email"] space
RedirectJobseeker(("Redirect\nJobseeker")) space
OneLoginUserInfo --> FindJobseeker
FindJobseeker --> ExistingJobseeker
ExistingJobseeker -- "No" --> CreateJobseeker
ExistingJobseeker -- "Yes" --> FirstTime
FirstTime -- "Yes" --> SetJobseekerId
FirstTime -- "No" --> EmailChanged
EmailChanged -- "Yes" --> UpdateJobseekerEmail
EmailChanged -- "No" --> RedirectJobseeker
CreateJobseeker --> RedirectJobseeker2
SetJobseekerId --> RedirectJobseeker2
UpdateJobseekerEmail --> RedirectJobseeker2
classDef start fill:#90ee90;
classDef end fill:#fa8072;
class OneLoginUserInfo start
class RedirectJobseeker,RedirectJobseeker2 end