The SAML assertion from an IDP contains user profile information like name and email that can be used by the SP to set up a user profile and keep the profile attributes up to date. Is there also a possibility to provide a user avatar / profile image in the context of an SAML assertion? Either as binary / base64 stream or at least a URL? Even if not defined in the standard, is there any IDP or SP out there that supports that?
The standard is completely open on what attributes to pass. You can any attribute in there with any data and name. So passing a URL or BASE64 data is perfectly find according to the standard. Each deployment (SP+Idp) decides on what attributes there are and what formats they should have.
That said, in the most common cases the entire SAML message is bounced over the client browser by posting the data from a hidden form field. It's not a suitable approach for a large set of binary data. Passing a URL to the image as an attribute is a perfectly fine approach to get around that. You can also look at the artifact binding, where the posted data just contains a token and the SP does a direct download of the actual SAML data from the Idp over a SOAP connection.
Related
Was wondering whether there is an example of full SSO login chain ? For example, user fills in the user name and IdP will check whether user exists. TestWebAppCore and TestIdPCore seem to implement "most" of it. Which API does need to be used when I need to do user validation ? An invalid login example would help to understand the API :)
You are correct that the TestIdPCore sample only shows the SAML 2.0 part of an IdP, it does not show user validation with e.g. username + password.
A user validation dialog can be added at this point https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/blob/master/test/TestIdPCore/Controllers/AuthController.cs#L44
I use the ITfoxtec.Identity.Saml2 component in FoxIDs which implements a full IdP including user validation. Users and password hashes are saved in CosmosDB and the username + password validation is based on password hash validation.FoxIDs is open source and free of charge. You are wellcomme to look at the FoxIDs code, maybe it is helpful. But I have to warn you, the FoxIDs code is complex and not that easy to read.
I am using NextAuth to login users using Twitter. This works fine and I receive the AccessToken and the Token Secret on the client side. However I need to query the Twitter API on the server side to get the logged in user profile information. Therefore I need to submit the AccessToken and Token Secret to the server with every request.
Should I combine the AccessToken and Token Secret into one string and send it as part of the Authorization Header parameter and parse it on the server side?
Security wise what would be the recommended way to send the access token information to the server?
I don't know if there's a best practice, but I'd say there are some thoughts that would argue against some of the solutions available.
First of, from a terminology standpoint, using the Authorization header would seem to be a misuse of its defined purpose (RFC 7235):
"... allows a user agent to authenticate itself with an origin server"
And:
"Its value consists of credentials containing the authentication
information of the user agent for the realm of the resource being
requested."
In this case, that's not what you're doing - the supplied credentials are not for the requested resource (action, rather), but information needed to by the requested action.
Secondly, I'd refrain from including any of the credentials in the path, for the reason that it's usually not treated as sensitive information from a logging perspective.
Since you're thinking security, I just assume you're enforcing HTTPS with your Functions. I also assume you're using HttpTrigger since you're saying you need to send the credentials with each request.
As I see it, you have 3 options:
Put it in a custom header (not Authorization)
Put it as query parameters
Put it in the body
Personal guidelines for the 3:
Header values as "meta" associated with the request that won't fit as query (or in URL).
Query parameters as parameterized "meta" associated with the resource/action.
Body as information to be used in processing an action (e.g. the state of a resource to be created).
So... I'd put it in the body.
All 3 options are secure (or well, as secure as the sever is configured). My best guess is that the body is the least logged information on a server. Primarily because the body can vary greatly in size, and would take up a lot of space if all request bodies were to be logged. Some servers might log the full URL (including query parameters), which is definitely a thing to take into consideration. Whether Azure does this "behind the scenes" for Functions, I don't know. The path is available as clear text via Application Insights, the query parameters are as far as I know not shown anywhere, unless explicitly written to the log by the implementation.
In any case, base64 encoding the information could be a last "good practice" step regardless of your choice, for example as "value:value" like BasicAuth.
I'm using https://graph.windows.net with credentials to access user data held within B2C AAD
string graphRequest = $"https://graph.windows.net/mytenancy.onmicrosoft.com/users/" + UserName + "?api-version=1.6"
Where UserName is the ObjectID for that user
I create an object to handle the resulting data, e.g.
displayName
mail
I can deserialize the result and use the info from the profile
I've now edited the SignUpSignIn policy to add a custom field, a string, called StandID
When I view the profile through Postman, the name of that appears to be
"extension_5295e65f1adc497186f72d63f5210d51_StandID": "E35"
However, I cannot seem to access the value via the same method, it comes back blank when I try and access it by the name given
Any idea what I'm doing wrong?
OK, so the answer came in two parts. The first was finding out how to identify the internal name it'd given - I did that by using Postman to show me the whole user profile as a json object
The second part was just a typo - because MSAL and ADAL are incompatible, yet I need to use both, my app is quite complex, and i was passing a value back from the API which I had the wrong receiver set up for in my app, once I realised that it all worked
I am the Service Provider. Also, a shout-out to this open source C# component (AspNetSaml), they made life a bit easier: https://github.com/jitbit/AspNetSaml
Anyhow, when I send a request to the IdP (in this case SalesForce), I am providing an ACS URL and I can see that it is set here in my xml:
xw.WriteAttributeString("ProtocolBinding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
xw.WriteAttributeString("AssertionConsumerServiceURL", _assertionConsumerServiceUrl);
(_assertionConsumerServiceUrl is what I really want it to redirect to, and I can see that it's set)
But what happens with Salesforce is that it always uses the ACS URL I was required to set when creating the Connected App:
I have my real ACS URL value blanked out, but that value is what it is always re-directed to.
There has to be a way. Imagine if instead of setting http://www.foo.com/, you wanted to instead redirect to: http://www.foo.com/?Some=1&Value=2&You=3&Want=4&ToAdd=5 ... and those values could be different depending on the user.
This has to be possible! Thanks!
I waited over a week, so as to not look like I'm answering my own questions just to build rep points.
Anyhow, as I discovered and confirmed here: https://salesforce.stackexchange.com/questions/210419/saml-sso-how-to-configure-a-dynamic-acs-url-salesforce-is-idp/210496
The RelayState is meant to direct the user after a successful login to a specific location in the application they're logging in to.
I need to set up Shibboleth IdP to validate user name and password against a custom application.
Our application exposes a REST API to which one can pass a user's credentials and either returns a 401 on failure or a JSON object with some user metadata on success.
I was able to achieve this in SimpleSamlPHP IdP with a 30-line class, but having to switch to Shibboleth, I am having a hard time finding directions to do the same there.
Reading through the documentation the suggested solution seems to be to create a custom back end for the password login flow but the Wiki does not explain in detail how to do this.
Can somebody point me out to some tutorials or sample code on which files need to be created or changed in order to do this (even basic examples of checking against a credential file or database would be fine)?
You are looking for an [External Authentication Flow] (https://wiki.shibboleth.net/confluence/display/IDP30/ExternalAuthnConfiguration)
For an example, see the shib-cas-authn3 project (https://github.com/Unicon/shib-cas-authn3). It uses the CAS Server to authenticate the users. It then creates an IdP session from information retrieved from CAS.