How does a SAML IdP communicate changes with the SP? - php

I'm working to integrate SAML SSO into an older PHP application. I am using simplesamlphp to set up my service provider and for testing purposes, I have a OneLogin dev account set up with a "SAML Test Connector (IdP w/attr)" test application as my IdP. I can successfully sign in, and I can log the user out using single log out. What I'm currently lost with is how the IdP communicates changes such as forced sign out and removing access to the application.
I had assumed that OneLogin would send a request to the URL I provide as the "Single Logout URL" once I forced a user to sign out or removed their privileges to the application along with enough data to identify the user. I would then expire that user's session in the service provider and everything would be good. But OneLogin isn't sending that request like I am expecting (it is only called after I initiate a single logout process on my end). The other option would seem to be me sending requests to OneLogin to validate the session frequently, but that seems inefficient.
What is the proper method for acquiring session/privilege updates from SAML?

From what I read, you don't get updates, you ask IdP about them (request user login or logout, which will check user status):
http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html#5.3.Single%20Logout%20Profile|outline
I don't think simplesamlphp would act as kind of enforcer of policies, you login as a user, you get your cookie until it expires.
I know you can set up session cookie duration to reasonable value in config.php of simplesamlphp, try that.

Related

Autheticate via SAML and create token in API

I am working on SAML authentication for my application which has the following architecture.
Frontend application written in Laravel - does not handle authentication
Backed API also written in Laravel which handles authentication
What I have now is a login form that has a login with SAML button which uppon clicked redirects to a Microsoft page and redirects a callback page on the frontend application with information from the saml request.
Now I need to authenticate the user and create a token, then make a session in the frontend application.
Since I was using SAML, I have no password to do a traditional authenticate.
This would mean that I need some API to which I pass some info from SAML to be able to check whether that email exists in the db and subsequently created a token.
But since this API is public, I can't just pass an email because that would allow someone to guess it.
How do I prevent this?
redirects a callback page on the frontend application with information
from the saml request
the information from the SAML request is your authentication event. The user has authenticated to your application by logging in at their Identity Provider (Microsoft page) and returning to your application with their SAML attributes.
If it was a traditional authentication with a username/password, once the password matches, you would create a session for them. In this case the password check was done by Microsoft and told your application it was successful by sending the SAML Response to your callback.
If you parse the SAML Response and extract the attributes you can use one of them to create the session. Something persistent such as eduPersonTargetedID which will always be the same value for that user will let you create their session. When they logout and log back in, that eduPersonTargetedID will have the same value in their SAML Response.
SAML Response samples are available here.

Central login with SAML and making site to work as identity provider

So my scenario goes like :
I have two sites a.com and site b.com and one authentication server cauth.com.
what client wants is ...
When user lands on a.com or b.com user fills in the login form on respective site , but the action of form will be on cauth.com (cauth.com/authenticate). when user is authenticated on cauth he is loggined on the both sites.
I am thinking to implement SAML to achieve the same and flow is like
after authentication iDP(cauth.com) will send SAML response to the both the service providers and user will be given access to both the sites .
I am novice in SAML and unable to get proper documentation and comprehension for the same.
What I want to know is :
Is my solution to the problem worth implementation ?
Is it possible to make site (cauth.com) as identity provider.I have looked at thread Making your PHP website into SAML Identity Provider but not able to get proper solution.
SimpleSamlPHP should be pretty easy to set up. You'll want to make a copy of the folder modules/exampleauth/ and then alter the file modules/<yournewmodule>/lib/Auth/Source/External.php to work for your site. The documentation is good though and it's definitely the easiest thing for your need, and the right one.
I should add that following the instructions to set up SimpleSamlPHP should give you a basic understanding of which metadata files are most important and where they live and how things interact.
I am not sure which technology you are using for your application. If you are free to switch to JAVA then I can suggest you Spring-Saml because its very easy to implement and fulfill your requirement. Spring-Saml has good documentation and online support as well being it as open-source project.
You can refer this link for Spring-saml and for code-repo use this link
You can integrate spring-saml in your abc.com and xyz.com application to make it Service provider(SP) and you can deploy it on different domain as well. Then you need to have one IDP (identity provider server) for your SPs. So you can use either ADFS with Active directory or LDAP to act as IDP.
We had similar requirement for our customer. I recently integrated spring-saml in my project.
Please let me know for any help
A federated Single Sign On (SSO) mechanism like SAML or OpenID Connect will give you what you want.
This comes with the important distinction that the login form would not be presented on a.com or b.com but those sites would rather redirect to cauth.com and the user would authenticate there. cauth.com would then send a verifiable "assertion" to a.com and b.com that the user has authenticated successfully. This constitutes one of the major goals of federated SSO, namely that the user credentials should not be presented/stored-by foreign websites and makes the means of authentication independent from the target websites ("Relying Parties").
So what you should be looking for is a suitable implementation of SAML or OpenID Connect for your platform (don't write it yourself!) and leverage that.
Shibboleth is open source and one of the most popular SSO solutions. It includes a SAML Identity Provider which you can download here: https://shibboleth.net/downloads/identity-provider/latest/ .
If your client is willing, one approach would be to use a cloud SSO provider like Okta which has a developer program and could make things easier.
I think there is a subtle misunderstanding in your description. For SAML authentication, if a user at site a.com either clicks a login link/button or tries to access a secure page, that user will receive an http 305 redirect to cauth.com. There the user will enter their credentials, and the user will be redirected back to a.com. If that user then goes to site b.com and tries to access secure content, b.com sends the user to cauth.com with the same http 305 redirect. This time, as there is an active session for the user's browser at cauth.com, the user does NOT see the credential form. Instead, the IDP returns the user with a successful authentication to b.com. It appears to the user that they are automatically logged on to site b, but in truth a SAML authentication flow has occurred.
Hans Z's answer elides the fact the that IDP only sends the assertions on the request of a or b (the Relying parties or RPs, also known as Service Providers or SPs). It is not a broadcast to all RPs.
I'll reinforce that SAML does NOT support a.com receiving the credentials from the user and then passing them to the authentication engine. This is a pattern one may be familiar with from LDAP.
Take a look at the sequence diagram in the wikipedia entry on SAML.
Follow below instruction to get SAML implimentation with PHP.
SAML login setup is very easy in php.
First register on onelogin server
https://www.onelogin.com/signup and create demo app on it. After
it follow all instruction to set Idp (Identity provider setting ) and
sp (service provider setting) to settings.php
https://developers.onelogin.com/saml/php
It worked perfect for me with CI and and php

PHP SAML IdP First

I'm trying to make a Client portal (IdP) in PHP.
That portal links to several SP's (like Magento, Google Analytics and Wordpress)
Seeing how this needs to works my IdP needs to initiate authentication. when clicked on a link to an SP the authentication needs to start.
So it needs an IdP first application. I try to set it up with SimpleSAML, the only problem is the initial explanation on the simpleSAML website isn't clear enough for me (https://simplesamlphp.org/docs/stable/simplesamlphp-idp) can someone give me some better or in depth explanation about IdP first?
this is a new client portal but the clients already have accounts with the mentioned sites and other sites, sometimes more than 1 account. Is it possible to connect those accounts without doing it myself but let the clients connect them?
If there are better solutions than SAML to this problem please don't hesitate to mention them
4.5 IdP initiated login
If you use a simpleSAMLphp IdP, and you want users to be able to bookmark the login page, you need to test IdP initiated login. To test IdP initiated login from a simpleSAMLphp IdP, you can access:
https://.../simplesaml/saml2/idp/SSOService.php?spentityid=<entity ID of your SP>&RelayState=<URL the user should be sent to after login>
Note that the RelayState parameter is only supported if the IdP runs version 1.5 of simpleSAMLphp. If it isn't supported by the IdP, you need to configure the RelayStateoption in the authentication source configuration.
As for account linking, it's my understanding that simple doesn't do this (it's getting out of the simple realm). To use it, you'll have to clean up accounts.
[edit]Actually, I suppose you could - though you'd have to build a structure to do it. You would need to somehow build a mapping of accounts from the corporate ID to the SP accounts at Wordpress, Google, etc.

How to manage session for a user logged in from mobile app in PHP?

I'm a PHP programmer by profession. So, I don't have any idea about iOS and Android coding.
The scenario is there is one website developed using a Social Networking PHP software titled "PHPFox".
Now there are two similar mobile apps which exactly replicates the functionality of this website. One mobile app is in iOS and another is in Android.
So, I've written a set of RESTful APIs where I'm accepting the request from mobile app, parse the request, pass the request parameters to the function which does the same job for website, get the response from this function, convert it into JSON format and sent it back to mobile app. For iOS and Android app I'm using the same set of REST API files.
When user logs in, the REST API for login gets called. Eventually the PHPFox function for authentication gets called, a security token is generated along with some other user data. With every login the different security token is generated by PHPFox. This data is set into the session. Now every time I call any of the functions through any REST API file the security token generated at the time of login is verified and only upon successful verification of token the PHPFox function gets called. This verification process is done internally by PHPFox. So no need to pass the security token explicitly or implicitly to any REST API call.
Till now everything works absolutely fine.
My doubt starts from here. I don't know whether the session is maintained in iOS/Android app. So, if session on server i.e. PHPFox gets timed out then what will happen to the app? Will it crash? Will the user have to login again? If user kills the app on the device and again comes to the app, does he/she have to do the login process again?
There are too many doubts in my mind. I get totally confused with these things.
Can someone please put more focus on the issue I'm facing? It would be really great if you could explain in detail.
Thanks.
REST is sessionless for its nature. You need to generate a token when user logged in. You must save this token on your mobile client.
For every request, you need to attach a valid token in request header and check it at server side.
If token expires, the token stored on a client is not valid. So, you need to login again because of 401 response. If token it's not correct you need to responde 400.
I hope that I'm helpful for you.
Unlike web browsers, iOS and android apps cannot maintain sessions. Usually, once a user has logged in (login credentials verified from server), its login credentials are saved on client side. Then the app gets data from server using session less REST api calls. This is how mostly it is done in mobile applications.
However, if you want the server session and mobile app go hand in hand (which i don't think is a good idea), the way is
1) When the user logs in, a security token is generated on the server side and saved on both server and client side.
2) The mobile app will be able to communicate with the server as long as the security token is valid.
3) When the session expires, the security token becomes invalid. Now there must be an understanding between server and client about the response when the session is expired. Now the mobile app must redirect the user to login page again. The user will login again and then communicate with the server. This should happen every time the session is expired.
If your are using Oauth 2 for athentication, here is the common setup:
User logs in on mobile app
If the credentials are ok, the server returns the access token, a refresh token and the token's lifetime
The mobile app stores those values + current timestamp
On the server's side, a garbage collector is configured to clear expired tokens
Before making any api call, the mobile app checks if the token is about to expire (with the help of the stored values). If the token is about to expire, the app sends the refresh token which instructs the server to generate a new access token
If you want users to stay connected, the app can be configured to check the access token periodically and request a new one if it's stale
Hope this helps.
Cheers
Your server should be completely stateless, and so no session should be stored.. a REST API is effectively just a data abstraction layer with optional security (through token)
So you API expose an authentication service, which will respond with an Authorization token to be used on subsequent requests as a header, this token should be a 1to1 relation with each user, and Universally Unique. It should also have an expire time, at which point your server responds with appropriate error response requesting your app to refresh the token, which can be done either via a separate refresh token system, or requesting that the user logs in again to refresh the token.
It is the APP which should maintain the state, not the server. The server is merely there for data purposes, and so should not rely on any kind of session based authentication.
A session is "something" that lives on the server. It can be an object storing details about the user (for instance session id, username, email address...) or any other data that will be required to process future requests (such as shopping cart details, delivery address...).
That "something" is typically an object, which can be stored in memory, in a database or even serialized and saved to the file system (I believe this is the default in PHP).
So when you say "I don't know whether the session is maintained in iOS/Android app", I'm afraid that doesn't make sense. Only the server can maintain sessions.
Typically, the only thing that the client would know (web browser or mobile app) is the session id (in the form of a token or GUID). That is the only thing the client/app needs to remember and it needs to be sent alongside any request to the server.
It could be stored as a cookie and/or sent to the server as a request header.
Then the server will read the session id/token from the cookies or header and will retrieve the session details from the place where it stores sessions (file system, memory or database). That is what happens behind the scene when you call session_start().
To read more about session handling and how to create custom session handler (which might be required in your case to get a token from the request headers):
http://php.net/manual/en/function.session-start.php
You should not worry about the session from the mobile development side.in Android we use SharedPrefrence and NSUserDefaults (Flag which maintains the session locally).
I dont have any experience working with PHPFox but this is how a mobile frontend should ideally handle the issues:
Case 1: Mobile app actively talking to server:
Session timeout stamp keeps bumping up and session stays alive.
Case 2: Mobile app active without any server communication (e.g. incoming phone call, moving between apps etc.):
Server session may or may not timeout.
If it times out, next query to server will fail auth and return an error.
App consumes this error and gracefully redirects to login screen with a message toast urging the user to login.
(This happens in my banking app)
Case 3: User kills the app on device and relaunches it:
The app should store the token either in sqllite or shared preferences. (Always logged in apps take this approach)
Upon relaunch, app can query the server with the presistent token.
If session is alive, communication goes through and user can
continue. If not, user goes to login screen as in Case 2.

Choosing the right OAuth2 grant type for PHP web app

I'm building a very typical web app product. It will likely have corresponding mobile apps in the future. I'm building it from the ground up with a REST API, which is secured using OAuth2. I've got OAuth2 working, and I'm able to connect successfully using various grant types.
What I'm a little confused about is what grant types to use for the actual web app. Here's what I had in mind:
Public API access
Before a user logs into the web app, some API access is required for things like user registration and password resets. I was thinking of using the client_credientials grant type. A simple client id and secret validation in return for an access token.
However, it seems totally unnecessary to request an access to token for every single public request or even for each session. It seems to make more sense to just generate ONE access token that my web app will always use.
Yet, this seems to go against how OAuth is designed to work. For example, access tokens expire. What is the right way of doing this?
Private user API access
Next, for a user to login to the web app I was planning on using the password grant type (resource owner password credentials). This approach allows me to save the user_id with the access token—so I know which user is logged in. Further, by using scopes I can restrict access within the API.
I plan to save the access token within the PHP session. As long as the PHP session is active they will remain logged into the web app.
Is this an appropriate design for user login?
For Public API Access:
One method is to skip tokens all together and just use Basic HTTP Authentication for API access. You could accept Client Credentials for this, and limit what clients can do using client-specific scopes. Github offers HTTP Basic authentication using user credentials for all their API calls.
For Private user API Access:
This is an interesting question because it begins to breech the line between Authentication and Authorization. OAuth is used for Authorization, so logging in users becomes dicy. Session management, for example, is something not covered by the OAuth2.0 spec.
However, this is a common use of OAuth2.0 anyway. You can use the password grant type, or any other grant type for that matter, to obtain an access token. A major downside is they have to trust your application with their password (Not a big deal for your own app, but for 3rd parties not so much). Also, being logged in one place does not necessarily mean being logged in somewhere else (rather than SSO, you have "linked accounts", so the sessions are managed separately). One way around this is to ALWAYS send users to the oauth authorize endpoint, and if their session is active on the OAuth2.0 Provider side, reroute them back to the client app with an access token or authorization code. This way, if the session is active with the OAuth2.0 provider, the client can immediately log them in.

Categories