Skip to content

Commit

Permalink
Refactor to use a constant and reduce number of variables
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdavidhamilton committed Nov 10, 2023
1 parent d95d246 commit bc7ddbe
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 77 deletions.
7 changes: 1 addition & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,10 @@ E2E=true
# Deployment environment
ENVIRONMENT=

# Gov One Authentication
GOV_ONE_LOGIN=true

# Base URI for Gov One Login requests
GOV_ONE_BASE_URI=https://oidc.integration.account.gov.uk

# Redirect URIs for Gov One Login redirects
# Replace localhost:3000 with the correct application root path
GOV_ONE_REDIRECT_URI=http://localhost:3000/users/auth/openid_connect/callback
GOV_ONE_LOGOUT_REDIRECT_URI=http://localhost:3000/users/sign_out

# DISPLAY SERVICE_UNAVAILABLE PAGE
MAINTENANCE = true
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ jobs:
DOMAIN: recovery.app
BOT_TOKEN: bot_token
GOV_ONE_BASE_URI: https://oidc.test.account.gov.uk
GOV_ONE_REDIRECT_URI: https://recovery.app/users/auth/openid_connect/callback
GOV_ONE_LOGOUT_REDIRECT_URI: https://recovery.app/users/sign_out

services:
postgres:
Expand Down
12 changes: 6 additions & 6 deletions app/helpers/gov_one_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,32 @@ def login_uri
client_id: Rails.application.config.gov_one_client_id,
nonce: SecureRandom.uuid,
state: SecureRandom.uuid,
redirect_uri: Rails.application.config.gov_one_redirect_uri,
redirect_uri: GovOneAuthService::CALLBACKS[:login],
}

session[:gov_one_auth_state] = params[:state]

gov_one_uri('authorize', params).to_s
gov_one_uri(:login, params).to_s
end

# @return [String]
def logout_uri
params = {
id_token_hint: session[:id_token],
state: SecureRandom.uuid,
post_logout_redirect_uri: Rails.application.config.gov_one_logout_redirect_uri,
post_logout_redirect_uri: GovOneAuthService::CALLBACKS[:logout],
}

gov_one_uri('logout', params).to_s
gov_one_uri(:logout, params).to_s
end

private

# @param endpoint [String]
# @param endpoint [Symbol]
# @param params [Hash]
# @return [URI::HTTP, URI::HTTPS]
def gov_one_uri(endpoint, params)
uri = URI.parse("#{ENV['GOV_ONE_BASE_URI']}/#{endpoint}")
uri = URI.parse(GovOneAuthService::ENDPOINTS[endpoint])
uri.query = URI.encode_www_form(params)
uri
end
Expand Down
68 changes: 32 additions & 36 deletions app/services/gov_one_auth_service.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
# Service for interacting with Gov One Login
# This service is initialised with an authorisation code and can be used to:
#
# - exchange an authorisation code for tokens (access and id)
# - exchange an access token for user info
# - decode an id token to get the user's gov one id
#
# More information on the Gov One Login integration environment can be found here:
# https://docs.sign-in.service.gov.uk/integrate-with-integration-environment/

# @see https://docs.sign-in.service.gov.uk/
class GovOneAuthService
# @return [Hash{Symbol => String}]
CALLBACKS = {
login: "#{Rails.application.config.service_url}/users/auth/openid_connect/callback",
logout: "#{Rails.application.config.service_url}/users/sign_out",
}.freeze

# @return [Hash{Symbol => String}]
ENDPOINTS = {
login: "#{Rails.application.config.gov_one_base_uri}/authorize",
logout: "#{Rails.application.config.gov_one_base_uri}/logout",
token: "#{Rails.application.config.gov_one_base_uri}/token",
userinfo: "#{Rails.application.config.gov_one_base_uri}/userinfo",
jwks: "#{Rails.application.config.gov_one_base_uri}/.well-known/jwks.json",
}.freeze

extend Dry::Initializer

option :code, Types::String
option :code, Types::Strict::String

# POST /token
# @return [Hash]
def tokens
http = build_http(token_uri)

token_request = Net::HTTP::Post.new(token_uri.path, { 'Content-Type' => 'application/x-www-form-urlencoded' })
uri, http = build_http(ENDPOINTS[:token])
token_request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/x-www-form-urlencoded' })
token_request.set_form_data(token_body)
token_response = http.request(token_request)

Expand All @@ -26,12 +38,12 @@ def tokens
{}
end

# GET /userinfo
# @param access_token [String]
# @return [Hash]
def user_info(access_token)
http = build_http(userinfo_uri)

userinfo_request = Net::HTTP::Get.new(userinfo_uri.path, { 'Authorization' => "Bearer #{access_token}" })
uri, http = build_http(ENDPOINTS[:userinfo])
userinfo_request = Net::HTTP::Get.new(uri.path, { 'Authorization' => "Bearer #{access_token}" })
userinfo_response = http.request(userinfo_request)

JSON.parse(userinfo_response.body)
Expand All @@ -52,34 +64,18 @@ def decode_id_token(token)

private

# @return [URI]
def token_uri
gov_one_uri('token')
end

# @return [URI]
def userinfo_uri
gov_one_uri('userinfo')
end

# @param endpoint [String]
# @return [URI]
def gov_one_uri(endpoint)
URI.parse("#{Rails.application.config.gov_one_base_uri}/#{endpoint}")
end

# @param uri [URI]
# @return [Net::HTTP]
def build_http(uri)
# @param address [String]
# @return [Array<URI::HTTP, Net::HTTP>]
def build_http(address)
uri = URI.parse(address)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true unless Rails.env.test?
http
[uri, http]
end

# @return [Hash]
def jwks
uri = gov_one_uri('.well-known/jwks.json')
http = build_http(uri)
uri, http = build_http(ENDPOINTS[:jwks])
response = http.request(Net::HTTP::Get.new(uri.path))
JSON.parse(response.body)
end
Expand All @@ -89,7 +85,7 @@ def jwt_assertion
rsa_private = OpenSSL::PKey::RSA.new(Rails.application.config.gov_one_private_key)

payload = {
aud: token_uri.to_s,
aud: ENDPOINTS[:token],
iss: Rails.application.config.gov_one_client_id,
sub: Rails.application.config.gov_one_client_id,
exp: Time.zone.now.to_i + 5 * 60,
Expand All @@ -105,7 +101,7 @@ def token_body
{
grant_type: 'authorization_code',
code: code,
redirect_uri: ENV['GOV_ONE_REDIRECT_URI'],
redirect_uri: CALLBACKS[:login],
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: jwt_assertion,
}
Expand Down
8 changes: 4 additions & 4 deletions app/views/gov_one/info.html.slim
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
= render 'learning/cms_debug'

- content_for :page_title do
= html_title t('gov-one.info.title')
= html_title t('gov_one.title')

.govuk-grid-row
.govuk-grid-column-one-half
= m('gov-one-info.body')
= m('gov_one.body')

- if current_user
= govuk_button_link_to t('gov-one-info.sign-out-button'), logout_uri
= govuk_button_link_to t('gov_one.links.sign_out'), logout_uri
- else
= govuk_button_link_to t('gov-one-info.sign-in-button'), login_uri
= govuk_button_link_to t('gov_one.links.sign_in'), login_uri

10 changes: 5 additions & 5 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class Application < Rails::Application
end

config.service_name = 'Early years child development training'
config.service_url = (Rails.env.production? ? 'https://' : 'http://') + ENV.fetch('DOMAIN', 'child-development-training')

config.internal_mailbox = ENV.fetch('INTERNAL_MAILBOX', '[email protected]')
config.middleware.use Grover::Middleware
config.active_record.yaml_column_permitted_classes = [Symbol]
Expand Down Expand Up @@ -69,11 +71,9 @@ class Application < Rails::Application
config.contentful_environment = ENV.fetch('CONTENTFUL_ENVIRONMENT', credentials.dig(:contentful, :environment))

# Gov one
config.gov_one_base_uri = ENV.fetch('GOV_ONE_BASE_URI', '#GOV_ONE_BASE_URI_env_var_missing')
config.gov_one_redirect_uri = ENV.fetch('GOV_ONE_REDIRECT_URI', '#GOV_ONE_REDIRECT_URI_env_var_missing')
config.gov_one_logout_redirect_uri = ENV.fetch('GOV_ONE_LOGOUT_REDIRECT_URI', '#GOV_ONE_LOGOUT_REDIRECT_URI_env_var_missing')
config.gov_one_private_key = ENV.fetch('GOV_ONE_PRIVATE_KEY', credentials.dig(:gov_one, :private_key))
config.gov_one_client_id = ENV.fetch('GOV_ONE_CLIENT_ID', credentials.dig(:gov_one, :client_id))
config.gov_one_base_uri = ENV.fetch('GOV_ONE_BASE_URI', '#GOV_ONE_BASE_URI_env_var_missing')
config.gov_one_private_key = ENV.fetch('GOV_ONE_PRIVATE_KEY', credentials.dig(:gov_one, :private_key))
config.gov_one_client_id = ENV.fetch('GOV_ONE_CLIENT_ID', credentials.dig(:gov_one, :client_id))

# @return [Boolean]
def live?
Expand Down
18 changes: 9 additions & 9 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -571,15 +571,15 @@ en:
%{criteria}
# /gov-one/info
gov-one:
info:
title: Gov One Login
body: |
# Gov One Login
This is some information about Gov One Login...
sign-in-button: Sign in with Gov One Login
sign-out-button: Sign out of Gov One Login
gov_one:
title: Gov One Login
body: |
# Gov One Login
This is some information about Gov One Login...
links:
sign_in: Sign in with Gov One Login
sign_out: Sign out of Gov One Login

# /settings/cookie-policy
cookie_policy:
Expand Down
3 changes: 1 addition & 2 deletions config/sitemap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
# }
# ]
#
protocol = Rails.env.production? ? 'https://' : 'http://'
SitemapGenerator::Sitemap.default_host = protocol + ENV['DOMAIN']
SitemapGenerator::Sitemap.default_host = Rails.application.config.service_url
SitemapGenerator::Sitemap.compress = false

# Run this command to update /public/sitemap.xml
Expand Down
7 changes: 2 additions & 5 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ services:
# app config
- DATABASE_URL=postgres://postgres:password@db:5432/early_years_foundation_recovery_development
- RAILS_ENV=development
- DOMAIN=app:3000
- DOMAIN=localhost:3000 # put back to app
- RAILS_SERVE_STATIC_FILES=true
# gov one login
- GOV_ONE_BASE_URI=https://oidc.integration.account.gov.uk
- GOV_ONE_REDIRECT_URI=http://localhost:3000/users/auth/openid_connect/callback
- GOV_ONE_LOGOUT_REDIRECT_URI=http://localhost:3000/users/sign_out
- GOV_ONE_BASE_URI=https://oidc.integration.account.gov.uk
volumes:
- .:/srv
tty: true
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ services:
- BOT_TOKEN=bot_token
- TIMEOUT_MINUTES=25
- GOV_ONE_BASE_URI=https://oidc.test.account.gov.uk
- GOV_ONE_REDIRECT_URI=http://recovery.app/users/auth/openid_connect/callback
- GOV_ONE_LOGOUT_REDIRECT_URI=http://recovery.app/users/sign_out
tty: true
stdin_open: true

0 comments on commit bc7ddbe

Please sign in to comment.