This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Saml | |
module_function | |
def authenticated?(session) | |
session[:saml_authenticated_at]&.between?(Settings.saml.expires_in.seconds.ago, Time.zone.now) || false | |
end | |
def auth_request_url(relay_state: nil) | |
OneLogin::RubySaml::Authrequest.new.create(settings, RelayState: relay_state) | |
end | |
def metadata_xml | |
OneLogin::RubySaml::Metadata.new.generate(settings) | |
end | |
def decode_response(message) | |
OneLogin::RubySaml::Response.new(message, settings: settings) | |
end | |
def decode_logout_request(message) | |
OneLogin::RubySaml::SloLogoutrequest.new(message) | |
end | |
def logout_response_url(logout_request, relay_state: nil) | |
OneLogin::RubySaml::SloLogoutresponse.new.create( | |
settings, | |
logout_request.id, | |
nil, | |
RelayState: relay_state | |
) | |
end | |
def settings | |
OneLogin::RubySaml::Settings.new.tap do |settings| | |
settings.assertion_consumer_service_url = Settings.saml.assertion_consumer_service_url | |
settings.sp_entity_id = Settings.saml.sp_entity_id | |
settings.idp_entity_id = Settings.saml.idp_entity_id | |
settings.idp_sso_target_url = Settings.saml.idp_sso_target_url | |
settings.idp_slo_target_url = Settings.saml.idp_slo_target_url | |
settings.name_identifier_format = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' | |
settings.idp_cert = File.read(Rails.root.join('config', 'onelogin.pem')) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Admin::SamlAuthenticationsController < Admin::ApplicationController | |
# SAMLで検証されるのでCSRF対策は不要 | |
protect_from_forgery except: :create | |
# sp_entity_id(metadata) | |
def show | |
render xml: Saml.metadata_xml | |
end | |
# このURLにアクセスするとIdPに飛ぶ(SP-initiated SSO) | |
def new | |
# RelayStateに入れた情報はそのままIdPから返ってくる | |
# これを使って認証後アクセスしようとしていたURLへリダイレクトする | |
# danger_next_pathではセッションやクエリパラメータに入れた「ログイン後リダイレクトしたいURL」を統一的に扱っている | |
relay_state = | |
if danger_next_path.present? | |
{ next: danger_next_path }.to_json | |
end | |
redirect_to Saml.auth_request_url(relay_state: relay_state) | |
end | |
# Assertion Consumer Service URL | |
def create | |
response = Saml.decode_response(params[:SAMLResponse]) | |
unless response.is_valid? | |
return redirect_to root_url, alert: 'ログインに失敗しました。不正なSAMLレスポンスです' | |
end | |
if user = User.where(foobar).find_by(email: response.name_id) | |
log_in user | |
session[:saml_authenticated_at] = Time.zone.now | |
# RelayStateがあればアクセスしようとしていたパスを取り出しそこにリダイレクトする | |
# next_urlではオープンリダイレクト対策を施す | |
redirect_to next_url(fallback_location: admin_root_url), notice: "#{user.name}でログインしました" | |
else | |
redirect_to root_url, alert: 'ログインに失敗しました' | |
end | |
end | |
# Single Logout URL | |
def destroy | |
logout_request = Saml.decode_logout_request(params[:saml_request]) | |
unless logout_request.is_valid? | |
return redirect_to root_url, alert: 'ログアウトに失敗しました。不正なSAMLリクエストです' | |
end | |
log_out | |
redirect_to Saml.logout_response_url(logout_request, relay_state: params[:relay_state]) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment