Authenticate using SAML-based Basic Authentication? - spring-security

I have a use case where a web application needs to let users authenticate in two different ways but using the same user data store (aka IDP) via SAML.
User's browser is redirected to IDP and redirected back with SAML assertion (aka WebSSO Profile).
User makes request to SP providing their credentials via Basic Authentication. SP would then need to send the user's credentials to the IDP and the IDP would provide an assertion all through a back channel (server to server).
I'm using Spring Security SAML extension. The sample application in Spring SAML contains both basic authentication with username and password and SAML-based authentication but the Basic Auth portion uses local accounts defined in the securityContext.xml file. I need to use the user accounts on the IDP. Is this possible? If so, how do I configure Spring SAML?

There is no standard SAML WebSSO mechanism which would allow SP to request assertion for a specific user by providing her credentials. You might want to look into WS-Trust standard which covers such use-cases using its Request security token methods (RST/RSTR calls). Another quite standardized way to do this is Client Credentials grant of OAuth 2.0. Both are out of scope for Spring SAML, but can be combined with it.

Related

ADFS2016 SAML2 to OAUTH2/OIDC

We have an MVC application (<myapp.somedomain.com>) .net 4.5.2 (OWIN/ADAL) that uses ADFS2016 for AuthN/AuthZ via OIDC/OAuth2. Users' credentials and attributes are stored in AD LDS. A client (X) requested to authenticate in the application via their IdP over SAML2. Is this possible WITHOUT making changes to the application?
The flow I am looking for; for this client the app’s URL would be (<myapp.somedomain.com/?client=x>). Our ADFS would recognize and redirect the client to their IdP where they would authenticate and than they would be send back to our ADFS along with some predefined claims. Our ADFS would map these claims to an Id Token / Access Token for our application to use. Am I dreaming or is this indeed feasible?
Any links to articles / documentation on how this could be achieved would be most helpful.
As #Wiktor suggests, you could add a SAML client-side stack to your app.
The other way is to federate ADFS with the SAML IDP.
When the user is redirected to ADFS, they use Home Realm Discovery to either redirect to the SAML IDP or authenticate on ADFS directly.
ADFS should handle the token conversions but you may have to fiddle around with the claims rules.

Using JWT to authorize REST API requests after SAML Authentication

I'm struggling theese days on the possible way to configure an Authentication + authorization system to consume a REST API from a mobile application.
Scenario:
We've developed 3 independent portals for a big customer that serves several users.
To enable a SSO for the 3 portals we've implemented a SAML authentication system using SimpleSAMLphp.
Every portal has a service provider and they make assertion requests against a central IdP.
The IdP checks username and password against a database where passwords are hashed and stored during registration.
After the login, the authorization on the portals is handled by the session on the server, and so far everything was fine.
Now the customer asked us to develop a mobile application that will require the users to login and access several of their protected resources collected during the usage of the 3 portals.
We've decided to develop a frontend application using ionic that will consume a REST API made in node.js that will serve all the data (both protected and unprotected resources).
Now here comes the question: to authorize access to protected resources on the Api we'd like to use JWT to easily achieve a stateless system.
The doubt is how to perform the authentication? We've the opportunity to check the credentials directly against the database skipping the SAML process, otherwise we've to implement a solution where the SSO IdP acts as authentication provider and then when an attempt is successful the API app will get the response from the idp and then issue a signed jwt to the consumer client. Is this second way a common implementation? Is it possible?
What path do you suggest to follow? The first could be very easy to achieve, but since we're using html+js for the app's frontend, if we decide to use the second solution probably in the near future we could recycle some code from the app to modernize some functions on the web portals, maintaining the jwt pattern and consuming the new Api also on the web.
I believe that in this case will be easier to ask a token to the new api using someway the logged in user's data already in the session of the portal. Sounds possible?
I hope that everything was clear, any help will be appreciated!
Thanks
The key goal here is to code your apps in the best way, via
the latest security standards (OAuth 2.0 and Open Id Connect).
SAML is an outdated protocol that is not web / mobile / API friendly, and does not fit with modern coding models.
Sounds like you want to do OAuth but you do not have an OAuth Authorization Server, which is a key part of the solution. If you could migrate to one you would have the best future options for your apps.
OPTION 1
Use the most standard and simple option - but users have to login with a new login screen + credentials:
Mobile or Web UI uses Authorization Flow (PKCE) and redirects to an Authorization Server to sign the user in
Mobile or Web UI receives an access token after login that can be sent to the API
Access token format is most commonly a JWT that the API can validate and identify the user from
The API is not involved in the login or token issuing processes
OPTION 2
Extend option 1 to federate to your SAML Identity Provider - enables users to login in the existing way:
The Authorization Server is configured to trust your SAML based identity provider and to redirect to it during logins
The SAML idp presents a login screen and then posts a SAML token to the Authorization Server
The Authorization Server issues OAuth based tokens based on the SAML token details
OPTION 3
Use a bridging solution (not really recommended but sometimes worth considering if you have no proper authorization server - at least it gets your apps using OAuth tokens):
Mobile or Web UI uses Resource Owner Password Grant and sends credentials to a new OAuth endpoint that you develop
OAuth endpoint provides a /oauth/token endpoint to receive the request
OAuth endpoint checks the credentials against the database - or translates to a SAML request that is forwarded to the IDP
OAuth endpoint does its own issuing of JWT access tokens via a third party library (if credentials are valid)
Web or Mobile UI sends JWT access token to API
API validates received JWT access token

Use SAML Token to Auth with OAuth

Just started POCing KeyCloak to hook up LDAP for user federation (really easy!) and set up a SAML Service Provider with Node.JS (took a bit more time to get the config right). See POC
Question:
Using KeyCloak as the sole Identity Provider, is it possible to set up a 3rd party service (Appian) as a SAML Service Provider, and use the SAML Username and/or Token(session_index) it receives to request an OAuth Token?
Preferably the 3rd party (trusted) service, behind the scenes, would make the OAuth request (with a client id?) to get an access token, and use the token to make API calls.
Seems like there could be two KeyCloak clients, one for SAML, one for OAuth, but then KeyCloak would be able to coordinate the auth under the covers.
You can exchange a SAML assertion (NOT its decoded contents) for an oAuth access token. This flow is described in RFC 7522 (SAML 2.0 Profile for OAuth 2.0 Client Authentication and Authorization Grants). In practice, this is an exotic use case and it's hard to implement. It assumes that the requester (client) has a way to acquire a SAML response from the IdP and wield it to grab an oAuth access token. To top it off, there are precious few IdPs that support RFC 7522 exchange. At the moment, Keycloak does not support it.
A more straightforward variation of the use case you're thinking about is an ability of a client to request any token (SAML, oAuth, ...) from an identity provider/authorization service without reauthenticating. This is possible with some providers but these mechanisms are proprietary to each provider. For example, Salesforce Identity service allows various tokens to be obtained if you send a request with a Salesforce session ID in a specific format.

OAuth2 Login (Not Authorization)

I have implemented an OAuth2 register workflow (in Java) according to rfc6749
I'm using GitLab as OAuth2 Provider.
After the user granted access to my application for his account, I get an OAuth Token (along with refresh token and other stuff), I am able to make API requests on behalf of the user, so this is working fine.
This way I can get the users e-mail adress which I use to create an internal user.
My questions are:
Is it practice to issue a token that is generated by my application for the user (along with the OAuthToken) or should I just use the token that has been issued by the OAauth Provider? (My App also has local auth with bearer tokens). This token will be used for further API - CLIENT communication (stored in Angular2 local storage as bearer)
How to do login only? When a OAuth User accesses my web service, how do I know that this user is a OAuth User and which OAuth Token belongs to him? How can the user login without providing e-mail or password? (The user has no password) I guess I have to redirect him to the OAuth Provider again, but I don't want my user to grant access everytime he logs in.
Answer 1:
Though you can use the token provided by OAuth provider, you SHOULD NOT use it considering the risk that may arise exposing it to the public.
Instead you should securely save the token provided by OAuth provider into the database and use another token for authentication of further api calls. (you could use JWT)
Answer 2:
There are two types of systems
Which always uses OAuth provider for identifying user. (Ex. Tinder)
Which provides both OAuth Login and Traditional login/signup. (Ex. Quora, Instagram)
If you want your application to follow 2nd approach, you should ask the user to create password for the first time when the user logs in using OAuth provider.
This will allow the user to log into your application by both methods, traditional as well as OAuth
To identify users of your application, you should either use HTTP session or issue your own tokens. Do not use tokens generated by the OAuth2 provider - they are meant to be used just by your backend (in role of an OAuth2 client).
To use an external authentication in your application, you probably want to use OpenID Connect, not a bare OAuth2. OpenID Connect extends OAuth2 and it's meant for authentication instead of the rights delegation. Then you use an implicit flow (instead of authentication code grant) with scope=openid, your frontend app (HTML+JavaScript) gets an ID token signed by the OAuth2 provider. After successful signature verification, your backend can trust that the client is the one described in the ID token (in its "sub" field). Then you can either keep using the ID token or generate your own token.

How does Spring Security SAML extension handle subsequent requests after authentication?

I'm using the Spring Security SAML extension for my SP. After a user is authenticated from the IDP, the SP uses some sort of method to allow subsequent calls to not have to be reauthenticated with the IDP. How is this done in the Spring Security SAML extension?
A related question:
Authenticating mobile users against SAML IDP
In the accepted answer from the above related question, the SP should create a token and pass it back to the client for future requests. I'm not seeing anything like this when watching the flow in Chrome's Network Tool. What should I be looking for?
Update 1: I'm coming to the conclusion that Spring SAML doesn't pass anything back to a browser in the form of a token. It must be keeping track of the user on the server side. Can I get confirmation on this? Is it possible to generate a token to pass back to the client in the case of a REST call?
Spring SAML is relaying on Spring Security for handling of user's authentication state. By default user state is stored in SecurityContext and Authentication objects which are put into user's HTTP Session (identified by secure cookie typically JSESSIONID which is passed to the browser). You'll be able to find all details related to this in the Spring Security documentation.
In case your user is calling REST APIs from browser where she authenticated, and the API is deployed together with the Spring Security application, the call will be providing same cookies as you would get for normal server calls and they will be authenticated using the same mechanism without need for any tokens.
In case you want to perform calls to a 3rd party REST API where you have not established a session or authenticated using other means, one way to secure such scenario is e.g. issue and use OAuth 2.0 Bearer tokens.
After the user is authenticated from the IDP, the IDP sends back a SAML assertion to the SP. The Spring Security SAML extension validates this assertion.
If the validation is successful, Spring Security establishes a user session, which is generally persisted through the cookie mechanism.
In the case of a REST service, your suggestion is basically what is done on OAuth-enabled REST services. The client sends an authorization token with each request.

Resources