Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/controllers/errors_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class ErrorsController < ApplicationController
layout false

skip_before_action :authenticate_auth_user!

def auth_error
# Renders app/views/errors/auth_error.html.erb
end
end
5 changes: 3 additions & 2 deletions app/controllers/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def keycloak_openid
omniauth_auth = request.env['omniauth.auth']
@user = AuthUser.from_omniauth(omniauth_auth)
if @user.persisted?
@relevant_role = AuthConfig.relevant_keycloak_role
if @user.persisted? && omniauth_auth[:extra][:raw_info][:pitc][:roles].include?(@relevant_role)
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: 'Keycloak') if is_navigational_format?
else
Expand All @@ -15,6 +16,6 @@ def keycloak_openid
end

def failure
redirect_to root_path
redirect_to '/auth_error'
end
end
10 changes: 10 additions & 0 deletions app/views/errors/auth_error.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3 text-center">
<h1>Authentication Error</h1>
<p>You do not have the necessary permissions to access this application.</p>
<p>Please contact an administrator if you believe this is an error.</p>
<%= link_to 'Go back to sign in', '/sign_in', class: 'btn btn-primary' %>
</div>
</div>
</div>
1 change: 1 addition & 0 deletions config/docker/keycloak/rails.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ LOCAL=false

ADMIN_ROLE=ADMIN
REALM=pitc
RELEVANT_KEYCLOAK_ROLE=puzzle

HOST_URL=http://keycloak:8080
KEYCLOAK_REDIRECT_HOST_URL=http://localhost:8080
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
get 'sentry_error', to: 'status#sentry_error'
end

get '/auth_error', to: 'errors#auth_error'
get root to: redirect(path: "/people")

scope "(:locale)", locale: LOCALE_REGEX do
Expand Down
4 changes: 4 additions & 0 deletions lib/auth_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def conf_admin_role
get_var_from_environment(:conf_admin_role, required: false)
end

def relevant_keycloak_role
get_var_from_environment(:relevant_keycloak_role, required: true)
end

def keycloak?
to_boolean(get_var_from_environment(:keycloak, required: false, default: false))
end
Expand Down
23 changes: 23 additions & 0 deletions spec/controllers/errors_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'rails_helper'

RSpec.describe ErrorsController, type: :request do
describe 'GET #auth_error' do
before { get '/auth_error' }

it 'returns a successful response' do
expect(response).to be_successful
end

it 'renders the auth_error template' do
expect(response).to render_template(:auth_error)
end

it 'does not use the application layout' do
expect(response.body).not_to include('<title>PuzzleSkills</title>')
end

it 'contains the correct error message' do
expect(response.body).to include('You do not have the necessary permissions')
end
end
end
41 changes: 41 additions & 0 deletions spec/controllers/omniauth_callbacks_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'rails_helper'

describe OmniauthCallbacksController do
before do
request.env['devise.mapping'] = Devise.mappings[:auth_user]
end

describe '#keycloak_openid' do
context 'when user has the required role' do
before do
allow(AuthConfig).to receive(:relevant_keycloak_role).and_return('puzzle')
request.env['omniauth.auth'] = mock_omniauth_user(['puzzle'])
get :keycloak_openid
end

it 'signs in the user' do
expect(subject.current_auth_user).not_to be_nil
end

it 'redirects to the root path' do
expect(response).to redirect_to(root_path)
end
end

context 'when user does not have the required role' do
before do
allow(AuthConfig).to receive(:relevant_keycloak_role).and_return('puzzle')
request.env['omniauth.auth'] = mock_omniauth_user(['another_role'])
get :keycloak_openid
end

it 'does not sign in the user' do
expect(subject.current_auth_user).to be_nil
end

it 'redirects to the auth_error path' do
expect(response).to redirect_to('/auth_error')
end
end
end
end
24 changes: 24 additions & 0 deletions spec/support/omniauth.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module OmniauthMacros
def mock_omniauth_user(roles = [])
OmniAuth::AuthHash.new(
provider: 'keycloak_openid',
uid: '123545',
info: {
name: 'Test User',
email: '[email protected]'
},
extra: {
raw_info: {
pitc: {
roles: roles
}
}
}
)
end
end

RSpec.configure do |config|
config.include OmniauthMacros
OmniAuth.config.test_mode = true
end