Skip to content

Commit

Permalink
Call DSI API for user roles on successful authentication
Browse files Browse the repository at this point in the history
The DfE SignIn API will return 404 if the user roles are not found for the specified organisation.
  • Loading branch information
steventux committed Sep 4, 2023
1 parent d02dd62 commit 1a7ec5c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ DFE_SIGN_IN_CLIENT_ID=checkrecordteacher
DFE_SIGN_IN_REDIRECT_URL=http://check.localhost:3000/check-records/auth/dfe/callback
DFE_SIGN_IN_SECRET=override-locally
DFE_SIGN_IN_ISSUER=https://dev-oidc.signin.education.gov.uk
DFE_SIGN_IN_API_BASE_URL=https://dev-api.signin.education.gov.uk
DFE_SIGN_IN_API_SECRET=override-locally
DFE_SIGN_IN_API_AUDIENCE=signin.education.gov.uk
GOVUK_NOTIFY_API_KEY=override-locally
HOSTING_DOMAIN=http://localhost:3000
HOSTING_ENVIRONMENT_NAME=local
Expand Down
18 changes: 17 additions & 1 deletion app/controllers/check_records/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,23 @@ class CheckRecords::OmniauthCallbacksController < ApplicationController
protect_from_forgery except: :dfe_bypass

def dfe
@dsi_user = DsiUser.create_or_update_from_dsi(request.env["omniauth.auth"])
auth = request.env["omniauth.auth"]

unless CheckRecords::DfESignIn.bypass?
begin
CheckRecords::DfESignIn::Client.new.get_user_access_to_service(
auth.extra.raw_info.organisation.id,
auth.uid
)
rescue CheckRecords::DfESignIn::Client::InvalidTokenError
return redirect_to check_records_sign_out_path
rescue CheckRecords::DfESignIn::Client::UserNotFoundError
flash[:warning] = "User not permitted to access this service"
return redirect_to check_records_sign_out_path
end
end

@dsi_user = DsiUser.create_or_update_from_dsi(auth)
session[:dsi_user_id] = @dsi_user.id
session[:dsi_user_session_expiry] = 2.hours.from_now.to_i

Expand Down
62 changes: 62 additions & 0 deletions app/lib/check_records/dfe_sign_in.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "hosting_environment"
require "jwt"

module CheckRecords
class DfESignIn
Expand All @@ -13,5 +14,66 @@ def self.bypass_active?
def self.review_app?
HostingEnvironment.review?
end

class Client
class InvalidTokenError < StandardError; end
class UserNotFoundError < StandardError; end

TIMEOUT_IN_SECONDS = 5

def get_user_access_to_service(org_id, user_id)
endpoint = "/services/#{service_id}/organisations/#{org_id}/users/#{user_id}"
response = client.get(endpoint)

handle_response(response)
end

def client
@client ||=
Faraday.new(
url: ENV.fetch("DFE_SIGN_IN_API_BASE_URL"),
request: {
timeout: TIMEOUT_IN_SECONDS
}
) do |faraday|
faraday.request :authorization, "Bearer", jwt
faraday.request :json
faraday.response :json
faraday.adapter Faraday.default_adapter
end
end

def handle_response(response)
case response.status
when 200
if response.body["success"] == false
raise InvalidTokenError, response.body["message"]
else
response.body
end
when 404
raise UserNotFoundError
when 401
raise InvalidTokenError
when 500
raise StandardError, "DFE Sign-in API Internal Server Error"
end
end

def service_id
ENV["DFE_SIGN_IN_CLIENT_ID"]
end

def jwt
@jwt ||= JWT.encode(
{
iss: ENV.fetch("DFE_SIGN_IN_CLIENT_ID"),
aud: ENV.fetch("DFE_SIGN_IN_API_AUDIENCE"),
},
ENV.fetch("DFE_SIGN_IN_API_SECRET"),
"HS256",
)
end
end
end
end

0 comments on commit 1a7ec5c

Please sign in to comment.