chrodriguez / redmine_omniauth_saml

Plugins that adds SAML authentication support for "Redmine"
GNU General Public License v2.0
38 stars 56 forks source link

Internal error when trying to login using SAML #47

Open varenius opened 4 years ago

varenius commented 4 years ago

Hello, I am trying to configure Redmine to use this plugin with my university login service. Environment: Redmine version 4.0.5.stable Ruby version 2.5.5-p157 (2019-03-15) [x86_64-linux-gnu] Rails version 5.2.3

I go to my redmine login page, then click the link to login wih SAML, get to the University server and provide my details, and press enter. Then I get a message on screen like

Internal error

An error occurred on the page you were trying to access. If you continue to experience problems please contact your Redmine administrator for assistance.

If you are the Redmine administrator, check your log files for details about the error.

Investigating I check "/var/log/apache2/error.log" but I only find one relevant line: App 24371 stdout: I, [2020-01-26T10:45:04.288274 #24371] INFO -- omniauth: (saml) Callback phase initiated. Looking further in "/opt/redmine/log/debug.log" I see a lot more info (where I have REMOVED some potentially sensitive information):

I, [2020-01-26T10:45:04.287710 #24371]  INFO -- : Started POST "/redmine/auth/saml/callback" for 94.255.250.60 at 2020-01-26 10:45:04 +0100
I, [2020-01-26T10:45:04.311045 #24371]  INFO -- : Processing by AccountController#login_with_saml_callback as HTML
I, [2020-01-26T10:45:04.311341 #24371]  INFO -- :   Parameters: {"SAMLResponse"=>"REMOVED", "provider"=>"saml"}
I, [2020-01-26T10:45:04.313357 #24371]  INFO -- :   Current user: anonymous
I, [2020-01-26T10:45:04.314952 #24371]  INFO -- : Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.4ms)
F, [2020-01-26T10:45:04.315578 #24371] FATAL -- :   
F, [2020-01-26T10:45:04.315631 #24371] FATAL -- : NoMethodError (undefined method `[]' for nil:NilClass):
F, [2020-01-26T10:45:04.315657 #24371] FATAL -- :   
F, [2020-01-26T10:45:04.315702 #24371] FATAL -- : plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:70:in `block (3 levels) in user_attributes_from_saml'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:69:in `each'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:69:in `inject'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:69:in `block (2 levels) in user_attributes_from_saml'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:65:in `each'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:65:in `block in user_attributes_from_saml'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:64:in `tap'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:64:in `user_attributes_from_saml'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb:21:in `user_attributes_from_saml'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml/user_patch.rb:12:in `find_or_create_from_omniauth'
plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml/account_controller_patch.rb:28:in `login_with_saml_callback'
lib/redmine/sudo_mode.rb:63:in `sudo_mode'

I suspect this has to do with me configuring my attributes the wrong way (I don't know much about this). Based on the example file I have configured /opt/redmine/config/initializers/saml.rb like this:

Redmine::OmniAuthSAML::Base.configure do |config| config.saml = { :assertion_consumer_service_url => "REMOVED", # OmniAuth callback URL :issuer => "REMOVED", # The issuer name / entity ID. Must be an URI as per SAML 2.0 spec. :single_logout_service_url => "REMOVED", # The SLS (logout) callback URL :idp_sso_target_url => "REMOVED", # SSO login endpoint :idp_cert_fingerprint => "REMOVED", # SSO ssl certificate fingerprint, SHA-1

Alternatively, specify the full certifiate:

#:idp_cert                       => "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
:name_identifier_format         => "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
:signout_url                    => "", # Optional signout URL, not supported by all identity providers
:idp_slo_target_url             => "",
:name_identifier_value          => "mail", # Which redmine field is used as name_identifier_value for SAML logout
:attribute_mapping              => {
# How will we map attributes from SSO to redmine attributes
  :login      => 'extra.raw_info.urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
  :mail       => 'extra.raw_info.urn:oid:0.9.2342.19200300.100.1.3',
  :firstname  => 'extra.raw_info.urn:oid:2.5.4.42',
  :lastname   => 'extra.raw_info.urn:oid:2.5.4.4'
}

}

config.on_login do |omniauth_hash, user|

Implement any hook you want here

end end

Parsing the SAMLResponse (which was REMOVED in the debug.log above) I find these attributes supplied by the login server:

<AttributeStatement>
<Attribute Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><AttributeValue>Eskil Varenius</AttributeValue></Attribute>
<Attribute Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><AttributeValue>Eskil</AttributeValue></Attribute>
<Attribute Name="urn:oid:2.5.4.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><AttributeValue>Varenius</AttributeValue></Attribute>
<Attribute Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><AttributeValue>REMOVED</AttributeValue></Attribute>
<Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><AttributeValue>REMOVED</AttributeValue></Attribute>
<Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><AttributeValue>REMOVED</AttributeValue>
<AttributeValue>REMOVED</AttributeValue></Attribute>
</AttributeStatement>

As far as I understand, it seems I get the right information back in the SAML response, but for some reason the plugin doesn't like it. Maybe I have matched the URN strings in the wrong format? Do you have any idea of where the error could be?

I see there has been a similar discussion in https://github.com/chrodriguez/redmine_omniauth_saml/issues/21#issuecomment-256945408 but I could not get my stuff to work using the things in there. As this was from an older version (redmine <4) I thought it may be worth filing a new issue.

Kind regards Eskil

varenius commented 4 years ago

I realised I could add the line logger.info(omniauth) to plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml/user_patch.rb i.e. :

module OmniAuthSamlUserMethods
    def find_or_create_from_omniauth(omniauth)
        logger.info(omniauth)

I then find in redmine/log/debug.log this message (where REMOVED are masked values): I, [2020-03-24T08:39:38.000470 #52519] INFO -- : #<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash> extra=#<OmniAuth::AuthHash raw_info=#<OneLogin::RubySaml::Attributes:0x000056486a4a4c60 @attributes={"urn:oid:2.16.840.1.113730.3.1.241"=>["Eskil Varenius"], "urn:oid:2.5.4.42"=>["Eskil"], "urn:oid:2.5.4.4"=>["Varenius"], "urn:oid:0.9.2342.19200300.100.1.3"=>["eskil.varenius@REMOVED"], "urn:oid:1.3.6.1.4.1.5923.1.1.1.6"=>["varenius@REMOVED"], "urn:oid:1.3.6.1.4.1.5923.1.1.1.9"=>["member@REMOVED", "employee@REMOVED"], "fingerprint"=>"REMOVED"}>> info=#<OmniAuth::AuthHash::InfoHash email=nil first_name=nil last_name=nil name=nil> provider="saml" uid="0yce5EnXNgbQM5jBqncS9oiQ/FYs50bO/KcDoJofbGg=">

so... the problem seems to be the part email=nil first_name=nil last_name=nil name=nil. Investigations continue...

varenius commented 4 years ago

Solution found! I am using the urn:uid:... strings which contain dots (.) ! And, in plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb there is a line h[symbol] = key.split('.') # Get an array with nested keys: name.first will return [name, first] This doesn't work for my strings. I used the Rails.logger function to log things to the redmine-log from this file like this: Rails.logger.info("stuff_to_log") And I see that the result I ger from the split is for example: I, [2020-03-24T09:36:25.732545 #55859] INFO -- : ["extra", "raw_info", "urn:oid:1", "3", "6", "1", "4", "1", "5923", "1", "1", "1", "6"] While I would like the array ["extra", "raw_info", "urn:oid:1.3.6.1.4.1.5923.1.1.1.6"]

Not sure how to properly fix this, but for now I have just hard-coded the split as follows:

            #h[symbol] = key.split('.')                # Get an array with nested keys: name.first will return [name, first]
            h[symbol] = ["extra","raw_info",key[15..-1]] # hard-coded to avoid the problem with dots (.) in urn:oid. See https://github.com/chrodriguez/redmine_omniauth_saml/issues/47

This works! I can now login again. Not sure how to properly adress mappings which have dots in them; perhaps a better way is to use a replacement char other than "." to divide the attribute mapping stings? For example using | which would mean I define:

# How will we map attributes from SSO to redmine attributes
:login => 'extra|raw_info|urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
:mail => 'extra|raw_info|urn:oid:0.9.2342.19200300.100.1.3',
:firstname => 'extra|raw_info|urn:oid:2.5.4.42',
:lastname => 'extra|raw_info|urn:oid:2.5.4.4'
}

and then in plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb

            h[symbol] = key.split('|')                # Get an array with nested keys: name|first will return [name, first]

This works for me. Worth modifying?