How can one enable SAML federation in the Cognito Hosted UI without advertising their customer list? - single-sign-on

I am building an enterprise app and federating signin using the Cognito Hosted UI solution, and people can sign up individually using any email, but they might also work for a company which has signed an enterprise deal with us and use SSO.
The desired workflow is one in which they input their signin email, then it is checked against our list of SAML Single Sign On providers, and if they match an enterprise client using SSO they are sent to the proper federation page; if they don't match any, they are taken to the general purpose login.
So far, I have successfully used the Hosted UI and the critical idpIdentifier parameter to create the desired behavior successfully. The following React code summarizes how this works:
hostedUILogin() {
const idpIdentifier = this.state.email.split("#")[1];
let url = `https://${domain}/oauth2/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectSignIn}`;
if (idpIdentifier) {
url += `&idp_identifier=${idpIdentifier}`;
}
window.location.assign(url);
}
This produces the desired effect. When somebody signs in with an email address that ends in "#corporatecustomer.com" they are taken to the SSO page for Corporation's federation. When somebody signs in with "#gmail.com", they are taken to the Cognito Hosted UI.
Unfortunately, the Hosted UI seems to be unable to help itself but to show off our customer list on the left-hand side.
I am unable to discover in the documentation or tutorials any way to use the Cognito Hosted UI without advertising all available SAML providers on the left hand side, thereby giving away our customer list.
I have tried taking away the IDP for this Hosted UI App in the App Client configuration, but then it no longer captures through the idp_identifier successfully.

If it helps to you, one of the solutions I found was to create a single User Pool per Corporate Customer

You can create different App Client, and you can enable only identity provider on the first one, and native username/password on the other one.
For each App Client, you can dynamically change your AWS Config on the client side.
On our use case, SSO users may not have the same identity provider name on their email domains so we have "Login with SSO" button, which first handles kind of "Home Realm Discovery" by sending a request to backend with user's email and that endpoint returns the identity provider name belong to that user. Then the client initiates the federated sign in (or direct call to the hosted UI with identity provider parameter).

Related

Identity Server Resource Owner flow with external Identity Provider

We have a project where the client requests the use of their own Identity Provider, in this case, it is SalesForce.
We secure the application using IdentityServer 3 and have configured it that for this client (based on parameters) it will use SalesForce as the IDP.
For the web app, no problem, Identity Server redirects to the Sales Force login page and everything works great.
Now we have a mobile app to build and the client would like to avoid having a web login page and would rather have a nice polished login form built in the application. This means that we will have to use the Resource Owner flow.
Now, the users creds are on SalesForce side so how does that work and is this at all possible in IdentityServer 3 ?
I see 2 possibilities but I kind of like neither of them:
Send the auth call to IdentityServer which should detect that it is up to SalesForce to validate the user and forwards the request there. I think it is not good as I would rather avoid having my IdentityServer dealing with credentials that he should not even know
Send a first auth call to SalesForce to get some "id token" that would then allow me to send another auth call to IdentityServer which will then recognize the "id token" and release an access token.
That seems like a stretch and forces the app to know that there is an IDP which is none of its business.
Any idea?

When we tell our customers that our website "supports" SAML 2.0, what would they expect?

So, when management tells us our website needs to "support SSO through SAML 2.0", with no additional details, what are they thinking?
What will our customers expect?
Note - The is not an open website, where everyone can join. To log in you need to be a configured user in the system. The customer's admins need to create an account in our system for each user.
So we aren't going to let just anyone who has an account with an IdP in to our website. We'll have to have some mechanism for mapping a SAML identity to our users.
How would our customers expect that to work?
Based on hints in your question, I am going to presume that you will be acting as a service provider.
To be what I would call a "good" service provider, I would expect the following:
You sign your AuthnRequests.
You provide a metadata endpoint that is kept up to date with your SP metadata to include current public keys for encrypting attributes (if necessary) to be sent to you as well as validating your AuthnRequest signatures.
You support dynamic consumption of my identity provider's metadata endpoint to keep your side of the connection up to date, especially with concern to my signing certificate.
You expose management of my identity provider configuration inside of your service provider mechanism to my IdP administrators through a web or API interface.
You either support a mechanism to automatically manage my users (like via SCIM or Graph or something else), or you support Just-In-Time provisioning based on an incoming assertion.
You allow me to decide my SAML Name ID format, and that format is per-tenant. As an example, I may want to use email address as the identifier, while another IdP may want to use sAMAccountName. e.g., john.doe#domain.com vs. johndoe.
You support Service-Provider-Initiated SSO. That means that the user shows up to partner1.yourdomain.com and get redirected for authentication to that partner's IdP, and that going to the location partner2.yourdomain.com would redirect to a different IdP.
As a service provider, you should make using your service easy and secure. By shifting to SAML, it allows you to get out of the business of password and user management because you get to put that back on the identity provider. It allows your users to not have to type in a password (or more, if you're doing MFA) to use your service, removing friction caused by security. It allows you to put the onus of authenticating the user back on the organization that owns the identity.
Your customers would expect that if they have an application that uses the SAML 2.0 client-side stack then when the application sends an AuthnRequest, they will see a login page on your site and once authenticated, the application will receive a set of assertions (claims) from your IDP via an AuthnResponse.
One of these assertions is NameID. This is the "primary key" between their system and yours. Normally this is UPN or email.
This mapping is outside of the SAML spec. There needs to be some kind of "on-boarding" for the customers.

Why should I use One tap sign in over Chrome's Credential Management API

Am a bit confused about the One tap sign in that was announced by google earlier this year. Our application already users Credential Management API in Chrome, which essentially provides the user with login options based on the credentials that user has saved for our site on previous visit (passwords that are saved in chrome). When I read the documentation for One tap sign in, it promises to do the same thing, but using Google's client api id. Our application has its own ID provider with our own database of user name and passwords, from the documentation it looks like One Tap sign in does not support custom ID providers. Can anyone shed more light on this, why would I use one against the other?
Thanks
Karthik
I see two major differences:
One Tap is passwordless - it uses a token based login that never exposes the user's password. Chrome Credential Management API stores and retrieves actual passwords in Chrome's password store.
One Tap is purely web based - Chrome Credential Management API relies on Chrome's specific implementation. One Tap is a purely web based workflow so it will work across browsers.
One Tap is a much better long term login solution in my opinion. The Credential Management API is experimental and currently only supported in Chrome.
https://developer.mozilla.org/en-US/docs/Web/API/Credential_Management_API#Browser_compatibility
I lead product development at Google for the one-tap/auto sign-in library, we designed it such that the library includes the Credential Management API and extends to provide assistance in account creation, secure passwordless, and cross-browsers support.
In particular, if you make a request for existing credentials with code like this:
googleyolo.retrieve({
supportedAuthMethods: [
"https://accounts.google.com",
"googleyolo://id-and-password"
],
supportedIdTokenProviders: [
{ uri: "https://accounts.google.com", clientId: "CLIENT_ID" }
]
});
then any saved username/passwords from the Credential Management API will be returned (in browsers supporting the API) along with token data for Google Accounts. The one-tap/auto sign-in JavaScript library wraps the Credential Management API for credential retrieval.
Furthermore, the library provides a googleyolo.hint method to show an email selector for one-tap selection of a verified email address to assist in new account creation, or to link to an existing account, and then be auto signed-in next time with token instead of password, across all browsers, so long as the same Google Account is active.
I'd suggest using the one-tap/auto sign-in library and consuming tokens as well as passwords in order to get assisted sign-up, keep existing users signed-in automatically, and provide functionality even if the browser does not support the Credential Management API.
As for the question about using your own database of username / password, the hope with this library is you could implement the ability to create accounts and auto sign-in to these and existing accounts with an OpenID Connect ID tokens representing the user's identity. With the one-tap / auto sign-in UX, these are not only much more usable, but far more secure then passwords and mitigate creation of weak/re-used passwords. Please consider this or, even better, a hosted auth solution like Firebase Auth or Auth0 and include the one-tap UX in the frontend UI.

Identity Server 3 - Silent sign-in / sign in without login page. Including single sign on

I have come across a number of articles that discuss a similar matter but I cannot find a definitive answer.
My company would like to begin using Identity Server 3, however one of the requirements is to be able to authenticate an external user without them having to manually enter their credentials.
This must be capable of providing single sign on capabilities also as we have 3 different systems and our users should only have to sign in once.
Essentially, the external user has their own CRM.
The CRM holds their username and password for our software.
They then click a button in their CRM to launch our application
This redirects them to our website with a payload containing their credentials
We call a web service to authenticate the user
It is fundamental that we do not change this process for our partners.
Can I implement a custom service provider to provide the authentication or is there some other way of achieving this? If so, could you point me in the right direction for how this can be done?
Many thanks
Craig
I would assume that you'd create a mechanism for their CRM to get a token at the time the client logs into their site and then have them send that token via url to your callback page. This would use the machine-to-machine type grant, or the client-credentials flow. Then that page could validate the token and log the user in. There would have to be some sort of unique identifier between the two systems like email or something. Just an idea.

REST API and client on same server, need API authentication?

First, let me describe the application: we are working on a web-based software which is some kind of custom help desk application. It requires the user to login (we use FOSUserBundle). After login the user is redirected to the dashboard. From the dashboard there is no more page reload, the frontend is build on Angularjs and the user can get anywhere within the application without page reload. You could speak of a single page application.
So the data that is presented to the user, is fetched from a rest api (we use FOSRestBundle). This works quite well at this point.
There is some kind of dilemma. Only our staff will access this application (for now). So a staff member needs to login to access the helpdesk. The data that is pushed to the frontend via angularjs is called via api, so the user that has just logged in needs to authenticate again on every request because of rest.
Problem: Since the backend runs on symfony2 let us just try to get the user object of the currently logged in user when an api call is made:
$this->get('security.context')->getToken()->getUser()
returns anon. that stands for anonymous, or
$this->getUser();
returns just null.
So the authenticated context seems to be gone when using the rest api. However when I call an action directly without rest, I can get user information.
So what we need is to secure our rest api and get user information on every api call. We don't want third party people to access our application, just staff. I am not familar with OAuth, but the user will be redirected to a third party page to Allow/Deny access to his data? This would not be an option for us.
Based on that information, do you have any suggestions or ideas how to secure the api and transport the user data so that getUser does not return null or anon. but the actuall logged in user?
there's another way to resolve your problem.
It's by using Certificates.
you can generate certificates then use Http tunneling (https obviousley), the server will ask for a certificate (you've to configure Apache for that but it's not a big challenge).
with this in place, you've to add a CertificateManageron the server side to ensure that the certificate is valid and to know who's calling the service (to be able to authenticate the user at each request), the CertificateManager(or what ever you'll call it) will probably have to be configured within you filters chaine (as known in the java world), et voilĂ 
Hop that help you,
Abderrazak
REST is stateless so you will have to send some kind of authentication/authorization in each request. You can use HTTP BASIC AUTH or something like OAuth.
Have a look at https://github.com/FriendsOfSymfony/FOSOAuthServerBundle
I'm kind of building our application in exactly the same architecture (RESTful API with Symfony2 back-end and AngularJS frontend.
Another way is to duplicate the api routes, so that you have the api routes protected by OAUTH and the api routes protected by the session, both of them pointing to the same controllers. The method was explained here: https://stackoverflow.com/a/22964736/435026