By: David Lamb user 26 Feb 2019 at 12:39 a.m. CST

7 Responses
David Lamb gravatar
I'm starting to build an ASP.NET Core web application, which I want to be my service provider. It currently runs at https://localhost:5001. The Gluu server is hosted on an EC2 in AWS. (I have an SSH tunnel open to that server. For the security group, inbound is accepting SSH traffic from my public IP, and outbound traffic is unrestricted.) I've configured the application to add SAML2 authentication (using the SustainSys.Saml2.AspNetCore2 NuGet package), so the "Saml2" login button automatically appears on the site's login page, but when I click it, and it sends me to the Gluu server, the message is: **Web Login Service - Unable to Respond. The login service was unable to identify a compatible way to respond to the requested application. This is generally due to a misconfiguration on the part of the application and should be reported to the application's support team or owner.** (Previously I was getting an "unregistered" error, but I think I fixed the SP location.) I configured SAML2 on my web app in Startup.ConfigureServices with the following code, after reading https://medium.com/the-new-control-plane/connecting-adfs-5-0-and-the-sustainsys-saml-v2-0-for-net-core-stack-1c8dd8f4aecd services.AddAuthentication() .AddSaml2(options => { // TODO: ****MUST**** REMOVE THIS LINE AS SOON AS IDP GETS A SECURITY CERT. VERY DANGEROUS. CREATES MAN-IN-THE-MIDDLE VULNERABILITY. System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; }; options.SPOptions.EntityId = new EntityId("https://myWebsiteUrl.com"); options.SPOptions.NameIdPolicy = new Sustainsys.Saml2.Saml2P.Saml2NameIdPolicy(true, Sustainsys.Saml2.Saml2P.NameIdFormat.EmailAddress); options.IdentityProviders.Add( new IdentityProvider(new EntityId("https://gluu.server.public.ip/idp/shibboleth"), options.SPOptions) { MetadataLocation = "https://gluu.server.public.ip/idp/shibboleth", AllowUnsolicitedAuthnResponse = true, LoadMetadata = true }); // options.SPOptions.ServiceCertificates.Add(new X509Certificate2("idp-encryption.crt")); }); My SP metadata, which I generated using https://www.samltool.com/sp_metadata.php, is: <md:entitydescriptor cacheduration="PT604800S" entityid="https://myWebsiteUrl.com" validuntil="2019-02-20T05:55:19Z" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> <md:spssodescriptor authnrequestssigned="false" protocolsupportenumeration="urn:oasis:names:tc:SAML:2.0:protocol" wantassertionssigned="false"> <md:singlelogoutservice binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" location="https://localhost:5001/Saml2/Logout"> <md:nameidformat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:nameidformat> <md:assertionconsumerservice binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" index="1" location="https://localhost:5001/Saml2/SignIn"> </md:assertionconsumerservice></md:singlelogoutservice></md:spssodescriptor></md:entitydescriptor> On the Gluu server, I added the Trust Relationship by specifying a "Single SP" entity type, with the metadata location as "File", and I uploaded the file. I did not specify a logout URL. I configured the "Relying Party" as SAML2SSO (I did not add SAML2ArtifactResolution or SAML2AttributeQuery), and I did not change any of the defaults: - includeAttributeStatement: (checked) - assertionLifetime: 300000 - signResponses: conditional - signAssertions: never - signRequests: conditional - encryptAssertions: conditional - encryptNameIds: never The custom NameId is enabled on the server, the source attribute is "Email", the Name is "Email", and the NameId Type is "emailAddress". The error is kind of vague. Any ideas???

By Mohammad Abudayyeh staff 26 Feb 2019 at 4:05 a.m. CST

Mohammad Abudayyeh gravatar
Hey David, We need to see the logs to better determine your issue. Coming off some of the notes you placed here are some thoughts : - Are you browsing in http ? - Metadata is not authorizing the response location requested by the SP. Is the AssertionConsumerServiceURL in the AuthnRequest like the one you have above in the `<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"` - Set AuthnRequestsSigned="true" , WantAssertionsSigned="true"

By David Lamb user 28 Feb 2019 at midnight CST

David Lamb gravatar
Progress! My AssertionConsumerService Location URL was indeed incorrect. It should have been "https://localhost:5001/Saml2/Acs". (I think.) I'm still getting an error, but am further along now. I removed settings related to the NameIdPolicy (which were getting marked as invalid), and now, when I call `_signInManager.GetExternalLoginInfoAsync()`, it just returns `null` instead of an actual `Microsoft.AspNetCore.Identity.ExternalLoginInfo` object. I don't know if this is related to ASP.NET Identity, or Gluu or SustainSys.

By Mohammad Abudayyeh staff 28 Feb 2019 at 2:31 a.m. CST

Mohammad Abudayyeh gravatar
Progress is always good ! Ok check the following : - Check the authentication scheme in your code - Is your `ResponseType` set to `code` ? If so try changing it to `OpenIdConnectResponseType.CodeIdToken` - You may have to construct your own `ExternalLoginInfo` class inorder to bypass getting null and get back the right info.

By David Lamb user 02 Mar 2019 at 7:24 p.m. CST

David Lamb gravatar
My code (see first note in this thread) does not specify any "authentication scheme". SustainSys does not provide any documentation on such a thing. I *can* set a `SignInScheme` property, but it's just a string value; I have no idea what value it would or should be. I looked through the various Gluu server configuration pages and couldn't find anything resembling an authentication scheme. Same thing for `ResponseType`. Is that something on Gluu server, or in my SP metadata, or in my code? One thing to note; I don't get passed to any kind of login form on the Gluu server; should that be happening? The series of HTTP requests upon clicking my SP's SAML login button is as follows: 1. GET to gluu server /idp/profile/SAML2/Redirect/SSO?SAMLRequest=xxxxxx, which 302s me to 2. GET /idp/profile/SAML2/Redirect/SSO?execution=e1s1, which 302s me to 3. GET /idp/Authn/oxAuth?conversation=e1s1, which 302s me to 4. GET /oxauth/restv1/authorize?response_type=code&client_id=xxxx&scope=openid+email+user_name&..., which 302s me to 5. GET /idp/Authn/oxAuth?code={guid}&scope=openid+user_name+email&...., which 302s me to 6. GET /idp/Authn/oxAuth?code={guid)..., which 302s me to 7. GET /idp/profile/SAML2/Redirect/SSO?execution=e1s1&_eventId_proceed=1, which gives me a 200 response Somehow I end up back at ACS. I see that response_code is set to "code" in step 4 above, but I have no idea how, why or where that's set. Do you?

By Mohammad Abudayyeh staff 03 Mar 2019 at 12:41 a.m. CST

Mohammad Abudayyeh gravatar
If you can get to your GUI go to configuration --> JSON configuration --> Press the oxAuth Configuration tab and scroll down to Response types. For further clarification , when you are receiving `null` from `_signInManager.GetExternalLoginInfoAsync()` that is because the provider is not redirecting you to the correct callback path or the provider is not able to direct you to the callback path ( in this case there is no issue with callback path configuration). So also make sure your paths are all in sync and correct.

By David Lamb user 12 Mar 2019 at 1:19 a.m. CDT

David Lamb gravatar
My response types listed on the gluu server include all combinations, in order: code, code id_token, token id_token, code token, code token id_token, id_token. I moved "code id_token" so that it was listed first, before "code", but that made no difference. Or is the service provider (my application) the party that specifies the response type? Because my SAML2 plugin, SustainSys.Saml2, doesn't seem to provide an option for customizing that. Is that what I need to find??? And how do I "make sure" that my paths are "in sync and correct"? What does that mean? Is there something I can look at to verify? On StackOverflow, somebody wrote that I should have an "identity.external" cookie, but I don't.

By Mohammad Abudayyeh staff 15 Mar 2019 at 4:25 a.m. CDT

Mohammad Abudayyeh gravatar
&gt; Or is the service provider (my application) the party that specifies the response type? Because my SAML2 plugin, SustainSys.Saml2, doesn't seem to provide an option for customizing that. Is that what I need to find??? Well both the application and the IDP must have matching response types. So you need to check what exactly your applications response type is. To my knowledge SustainSys.Saml2 uses `id_token` usually but I am not sure, you can try setting only `code` and or only `id_token`. &gt; And how do I "make sure" that my paths are "in sync and correct"? What does that mean? Is there something I can look at to verify? What I mean by that is the paths of your connections.For example, make sure your IDP url is correct, callback path , make sure your metadatas and entity ID urls are all correct and actually loading ( An extra space, or line in the metadata file can cause this )...etc. Hence, &gt; when you are receiving null from _signInManager.GetExternalLoginInfoAsync() that is because the provider is not redirecting you to the correct callback path or the provider is not able to direct you to the callback path ( in this case there is no issue with callback path configuration). Please update us on your status.