forked from discourse/discourse-saml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin.rb
159 lines (131 loc) · 5.62 KB
/
plugin.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# name: discourse-saml
# about: SAML Auth Provider
# version: 0.1
# author: Robin Ward
require_dependency 'auth/oauth2_authenticator'
gem 'macaddr', '1.0.0'
gem 'uuid', '2.3.7'
gem 'ruby-saml', '1.3.1'
gem "omniauth-saml", '1.6.0'
request_method = GlobalSetting.try(:saml_request_method) || 'get'
class SamlAuthenticator < ::Auth::OAuth2Authenticator
def register_middleware(omniauth)
omniauth.provider :saml,
:name => 'saml',
:issuer => Discourse.base_url,
:idp_sso_target_url => GlobalSetting.saml_target_url,
:idp_cert_fingerprint => GlobalSetting.try(:saml_cert_fingerprint),
:idp_cert => GlobalSetting.try(:saml_cert),
:attribute_statements => { :nickname => ['screenName'] },
:assertion_consumer_service_url => Discourse.base_url + "/auth/saml/callback",
:custom_url => (GlobalSetting.try(:saml_request_method) == 'post') ? "/discourse_saml" : nil
end
def after_authenticate(auth)
result = Auth::Result.new
if GlobalSetting.try(:saml_log_auth)
::PluginStore.set("saml", "saml_last_auth", auth.inspect)
::PluginStore.set("saml", "saml_last_auth_raw_info", auth.extra[:raw_info].inspect)
::PluginStore.set("saml", "saml_last_auth_extra", auth.extra.inspect)
end
uid = auth[:uid]
result.name = auth[:info].name || uid
result.username = uid
if auth.extra.present? && auth.extra[:raw_info].present?
result.username = auth.extra[:raw_info].attributes['screenName'].try(:first) || uid
end
if GlobalSetting.try(:saml_use_uid) && auth.extra.present? && auth.extra[:raw_info].present?
result.username = auth.extra[:raw_info].attributes['uid'].try(:first) || uid
end
result.email = auth[:info].email || uid
result.email_valid = true
if result.respond_to?(:skip_email_validation) && GlobalSetting.try(:saml_skip_email_validation)
result.skip_email_validation = true
end
current_info = ::PluginStore.get("saml", "saml_user_#{uid}")
if current_info
result.user = User.where(id: current_info[:user_id]).first
end
result.user ||= User.where(email: Email.downcase(result.email)).first
if GlobalSetting.try(:saml_clear_username) && result.user.blank?
result.username = ''
end
result.extra_data = { saml_user_id: uid }
result
end
def after_create_account(user, auth)
::PluginStore.set("saml", "saml_user_#{auth[:extra_data][:saml_user_id]}", {user_id: user.id })
end
end
if request_method == 'post'
after_initialize do
module ::DiscourseSaml
class Engine < ::Rails::Engine
engine_name "discourse_saml"
isolate_namespace DiscourseSaml
end
end
class DiscourseSaml::DiscourseSamlController < ::ApplicationController
skip_before_filter :check_xhr
def index
authn_request = OneLogin::RubySaml::Authrequest.new
metadata_url = GlobalSetting.try(:saml_metadata_url)
settings = nil
if metadata_url
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
settings = idp_metadata_parser.parse_remote(metadata_url)
settings.idp_sso_target_url = GlobalSetting.saml_target_url
settings.idp_cert ||= GlobalSetting.try(:saml_cert)
else
settings = OneLogin::RubySaml::Settings.new(:idp_sso_target_url => GlobalSetting.saml_target_url,
:idp_cert_fingerprint => GlobalSetting.try(:saml_cert_fingerprint),
:idp_cert => GlobalSetting.try(:saml_cert))
end
settings.compress_request = false
settings.passive = false
settings.issuer = Discourse.base_url
settings.assertion_consumer_service_url = Discourse.base_url + "/auth/saml/callback"
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:protocol"
saml_params = authn_request.create_params(settings, {})
@saml_req = saml_params['SAMLRequest']
render text: <<-HTML_FORM
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<body onload="document.forms[0].submit()">
<noscript>
<p>
<strong>Nota:</strong>Ya que tu navegador no soporta JavaScript,
necesitas apretar una vez el siguient botón "Continuar" para proceder.
</p>
</noscript>
<form action="#{GlobalSetting.saml_target_url}" method="post">
<div>
<input type="hidden" name="SAMLRequest" value="#{@saml_req}"/>
</div>
<noscript>
<div>
<input type="submit" value="Continuar"/>
</div>
</noscript>
</form>
</body>
</html>
HTML_FORM
end
end
DiscourseSaml::Engine.routes.draw do
get '/' => 'discourse_saml#index'
end
Discourse::Application.routes.append do
mount ::DiscourseSaml::Engine, at: "/discourse_saml"
end
end
end
title = GlobalSetting.try(:saml_title) || "SAML"
button_title = GlobalSetting.try(:saml_button_title) || GlobalSetting.try(:saml_title) || "with SAML"
auth_provider :title => button_title,
:authenticator => SamlAuthenticator.new('saml'),
:message => "Autentificando con #{title} (asegurate que cualquier bloqueador de ventanas emergentes no este activado)",
:frame_width => 600,
:frame_height => 380,
:background_color => '#003366',
:full_screen_login => GlobalSetting.try(:saml_full_screen_login) || false,
:custom_url => request_method == 'post' ? "/discourse_saml" : nil