Can i achieve single sign on with openid - single-sign-on

I have been reading a lot on Single Sign on and OpenId
I have checked the documentation for OpenId and Single Sign On on the below Link
Single Sign On
http://rashidi.zin.my/geek-talks/2009/06/30/php-mysql-curl-single-sign-on-with-multiple-domains.html
http://www.opengroup.org/security/sso/sso_intro.htm
http://www.authenticationworld.com/Single-Sign-On-Authentication/
http://merbist.com/2012/04/04/building-and-implementing-a-single-sign-on-solution/
https://wiki.queensu.ca/display/itsd/Single+Sign-On
https://github.com/jasny/sso#readme
https://lw.microstrategy.com/msdz/MSDL/940/docs/mergedProjects/websdk/topics/sso/SSO_Single_Sign-on.htm
OpenId
http://openidexplained.com/
http://openid.net/pres/protocolflow-1.1.png -- Flow Diagram
http://wiki.openid.net/w/page/12995226/Run%20your%20own%20identity%20server
Simple concept what i understood on Single Sign on can be explained as below
User hits domain1.com.
domain1.com sees there's no session cookie.
domain1.com redirects to sso.com
sso.com presents login page, and take credentials
sso.com sets session cookie for the user
sso.com then redirects back to domain1 to a special url (like domain1.com/ssologin)
the ssologin URL contains a parameter that is basically "signed" by the sso.com. It could be as simple as a base64 of encrypting the loginid using a shared secret key.
domain1.com takes the encrypted token, decrypts it, uses the new login id to log in the user.
domain1 sets the session cookie for the user.
Now, the next case.
User hits domain2.com, which follows domain1 and redirects to sso.com
sso.com already has a cookie for the user, so does not present the login page
sso.com redirects back to domain2.com with the encrypted information
domain2.com logs in the user.
OpenId Concept what I got can be explained as
OpenID allows you to use an existing account to sign in to multiple websites, without needing to create new passwords.
An OpenID is a way of identifying yourself no matter which web site you visit.
Now My problem is even after reading a lot of documentation, am not sure will i be able to achieve single sign on using openID and this is very important for me to know before i start my code.
Is there any way where i can upload my database to OpenId for Authentication, So my users do not need to go through all the drill again.
I will really appreciate if anyone has implemented this earlier or has any reference for me to make this clear

Yes, OpenID will give you single signon across web applications that may live in different domains. Note that OpenID 2.0 (which is the subject of the links that you point to) was deprecated and followed up by OpenID Connect, see: http://openid.net/specs/openid-connect-core-1_0.html#Introduction
There are a number of product and libraries that you can use to build on:
http://openid.net/developers/libraries/

Related

keycloak - realm resolution based on username (email address)

I'm working on a multi tenant project where usernames are actually their email addresses and the domain of the email serves as a tenant identifier.
Now in keycloak I'll have different realms per tenant, but I want to have a single login page for all tenants and the actual realm that will do the authentication to be somehow resolved by the username (email address).
How do I go about doing that?
I found a thread on the mailing list (that I cant find now...) that discussed the same problem. It was something along the lines of - create a main realm that will "proxy" to the others, but I'm not quite sure how to do that.
I think Michał Łazowik's answer is on the right track, but for Single-Sign-On to work, it needs to be extended a little.
Keep in mind that because of KEYCLOAK-4593 if we have > 100 realms we may have to have multiple Keycloak servers also.
We'll need:
A separate HTTP server specifically for this purpose, auth-redirector.example.com.
An algorithm to determine the Keycloak server and realm from a username (email address).
Here would be the entire OAuth2 Authorization Code Flow:
An application discovers the user wants to log in. Before multiple realms, the realm's name would be a constant, so the application would redirect to:
https://keycloak.example.com/auth/realms/realname/protocol/openid-connect/auth?$get_params
Instead, it redirects to
https://auth-redirector.example.com/?$get_params
auth-redirector determines if it itself has a valid access token for this session, perhaps having to refresh the access token first from the Keycloak server that issued it (the user could have logged out and is trying to login as a different user that is served by a different realm).
If it has an valid access token we can determine the Keycloak server and realm from the username or email address in the access token and redirect to:
https://$keycloak_server/auth/$realm/realname/protocol/openid-connect/auth?$get_params
from here, the OAuth2 Authorization Code Flow proceeds as usual.
Else if it doesn't have a a valid access token, the auth-redirector stores the original app's $get_params as session data. It presents a form to the user asking for a username. When the user submits that, we can determine the Keycloak server and realm to use and then auth-redirector itself logs in to the Keycloak server using its own $get_params. Once the auth-redirector gets a call-back, it retrieves the access+refresh token from the Keycloak server and stores them in session data. It then, finally, redirects back to that same keycloak server and realm with the callers original $get_params (from session data). And the OAuth2 Authorization Code Flow proceeds as usual.
This is definitely a hack! But I think it could work. I'd love to try it out some day, time permitting.
Other hacks/solutions are needed for other OAuth2 flows...
The idea from the mailing list is to write a service (let's say auth-redirector.example.com) that has a single input field for email, finds realm based on domain and redirects to that realm's keycloak endpoint (e.g. auth.example.com/auth/realms/realm-name/etc…) while keeping all GET params.
You can find examples of direct login/registration URLs here: https://lists.jboss.org/pipermail/keycloak-user/2016-July/007045.html
One usability problem is that users would have to provide their email twice, I have not yet found a way to pass the username via the login URL.

django rest framework - understanding authentication and logging in

I am a beginner to django rest framework (and to REST in general) and I have a server side which (for now) has a UserViewSet which allows to register new users and I can POST to the url from my android app just fine (I get 201 CREATED).
I read a lot about it, but I don't seem to fully the understand the concept of Login and Authentication in REST frameworks and specifically in django rest framework, and how it works.
Do you "Log in" (like in facebook for example) and then you can make requests?
What I understand\heard off:
you can Login to a API\website using your username and password (assuming off course that you have registered as a user and you are in the user database).
After you are Logged in - you will be able to make requests to views that allow access only to logged in\authenticated users.
Is that somewhat correct? I mean, is there a "Log in" url where you login and that's it? you are authenticated?
Also read somewhere that there isn't actually a login url, and you have to add your username and password to each request and then the request has to check if your details are in the User database?
To sum up, I am not really sure how does authentication/logging in (same thing?) happens in django REST framework... and would really appreciate a good explanation or an example..
Thanks a lot!
In a normal web application (removing the API from the question), a user would "log" in with their credentials (username/password, social tokens, etc.) and would receive a session cookie (assigned by Django) that allows them to authenticate in future requests on behalf of a user (realistically, themselves). This session cookie stays on their system for a limited period of time (two weeks by default) and allows them to freely use the website without authenticating again. If the session cookie needs to be removed, such that the person can no longer authenticate, the web application typically destroys the session cookie (or clears the session) which effectives "logs them out".
In the case of an API, it all depends on how the authentication works.
SessionAuthentication works just like as described above, as it uses Django's internal session system.
TokenAuthentication remembers the authentication information through a database-backed token (which is transmitted in the Authorization header) instead of a session cookie.
BasicAuthentication authenticates on every session (no persistent session) by passing the username and password on every request (base64 encoded through the Authorization header).
Other authentication methods generally work in the same way as TokenAuthentication.
So, here are some answers to specific questions which were raised
Do you "Log in" (like in facebook for example) and then you can make requests?
Using BasicAuthentication, you "log in" on every request by providing your credentials. With token-based authentication (TokenAuthentication, OAuth 2, JWT, etc.), you "log in" to receive the initial token and then your authorization is confirmed on every request.
Also read somewhere that there isn't actually a login url, and you have to add your username and password to each request and then the request has to check if your details are in the User database?
This is basic access authentication which you can use in DRF using the BasicAuthentication class.

Browser based OAuth / OpenID with persistent login

We have a regular web application with cookie based auth and now we want to split frontend and backend (api) in order to have third-party public API. So our backend will be on one domain and frontend on another one.
For authorization we would like to switch for OAuth 2 with JWT. In this case our frontend app will have to use access_token instead of cookie session and it brings a big old question:
How To Remain Logged In - The Infamous "Remember Me" Checkbox (part II from Form based authentication for websites)
From OAuth2 point of view our frontend application going to use something between Resource Owner Password Credentials Grant and Implicit Grant. It is closer to Password Credentials Grant since we still going to use usual login form and won't redirect user to another domain in order to sign in. At the same time it is closer to Implicit Grant since it's all going to be browser-only & JavaScript based when access_token will be saved in browser.
The RFC says the authorization server MUST NOT issue a refresh token if you use Implicit Grant and my question is if it's still valid in this use case when you don't really use a 3-d party OAuth but your own api? Instinctively I feel that having refresh_token in browser is a security hole and would like to confirm it with you guys, but that refresh_token seems to be the only way to have persistent login working the same way as we had with cookies.
**UPD** after #FlorentMorselli comment:
The OpenID specs still do not answer my question if I can use refresh_token with browser only application
Google says they provide refresh_token only for access_type=offline
OpenID Connect Core says you cannot use Refresh Token with Implicit Flow
OpenID Connect Core says nothing about using refresh_token with Hybrid Flow
There's only one place where it says something promising about refresh_token with Hybrid Flow, but nothing precise
UPD2 thanks to #reallifelolcat
It looks like OpenID Connect does not explicitly support Resource Owner Password Credentials Grant, meaning you have to redirect user to OpenID Connect server to perform login. Do you know if there is another way to authenticate with user credentials over OAuth 2.0?
I believe splitting api and frontend is getting more common these days and I'd appreciate it if you share how you solve this Persistent Login issue and if you drop it completely and force user to re-login every X weeks.
Thanks!
Access tokens and refresh tokens have nothing to do with login with OpenID Connect. These are only for authorizing access to user profile information and for perhaps authenticated service calls to your public API after the fact of login. Refer to the spec for the difference between the ID Token and the Access Token.
If you are going to use OpenID Connect for login, then from what you've wrote so far, it sounds like you need to host your own OpenID Provider (OP) since you want to avoid going to another domain to sign in:
we still going to use usual login form and won't redirect user to another domain in order to sign in.
If you want to be your own Identity Provider, then more power to you. This means that you going to have to deploy your own working instance of an OpenID Connect server, complete with authorization and token endpoints.
Now this is the part where your persistent login comes in. Your browser webapp will be a relying party to the OP server you now have. When a user tries to login to your browser app using OpenID Connect, they will need to authenticate themselves to your OP server. Going through the OIDC flow, your browser app will get an ID token containing an issuer/subject pair identifying the user.
It's up to you to determine how the user stays logged into your OP server, but as long as the user at least authorizes the browser app once:
http://openid.net/specs/openid-connect-core-1_0.html#Consent
then you can save that consent for all future requests by this browser app to login, and therefore maintain a persistent login.
You're going to have to consider how you're going to handle sessions management, but it sounds like you have some cookie thing going already so you might be able to use that (see this answer: OpenID sign in mechanism - Stay signed in ). Otherwise, you're going to end up with a situation where your browser webapp has to get a new id token all the time.
Also as Florent mentioned, there are security considerations you should consider when doing a public client thing that your browser based webapp would be. Example:
https://www.rfc-editor.org/rfc/rfc6749#section-10.16

Rest application and authorization

I would like to build my own REST app.
I'm planning to use oAuth as a main auth approach.
The question is: Can I use login and password as client_id and client_secret (in terms oAuth spec) ?
I don't have any third side applications, companies, sites etc... which will authenteficate my users.
I have my own REST server and JS-application.
Whole site will be made in usual(RPC) approach, but some private part will be done as RESTfull service, with enough stand-alone JS application.
UPDATED: I'm not sure that I even need full oAuth support. It seems to me that I can ask login and password on https page and then generate some token. Later i could use it to check is this user authenticated already or not. But in this case this oAuth become almost the same what we have in web aplications. I do not need oAuth to athorize users ?
I'm not consider HTTP(s) authotization because i don't want to send evrytime user and password to server.
No.
One if the main reasons OAuth exists is to allow integrations without users compromising their usernames and passwords.
If you plan on using username and password, look into xAuth as an option if you still want to sign your requests. More info: https://dev.twitter.com/docs/oauth/xauth.
But you could likely just as well go for HTTP Basic Authentication. At least if you publish your API over SSL. More info: http://en.wikipedia.org/w/index.php?title=Basic_access_authentication
I think you might get a better answer on the security site. See, for example, this question.
In any case, you need to start with a detailed assessment of what attacks you are trying to prevent and what attacks are "acceptable.". For example, if you are using HTTPS then you can probably accept the remaining danger of a man-in-the-middle attack, because it would require forging an SSL certificate. It is harder to say in general if a replay attack is acceptable.
One reasonable solution would be to create a time-limited temporary token by having the user authenticate over HTTPS with the username and password, generating a secure token with an expiration date, and then sending that token and expiration date back to the client. For example, you can create a (reasonably) secure token by taking the SHA1 hash of a secret plus the user name plus the expiration timestamp. Then the client can include the token, the user name, and the authentication timestamp in future requests and you can validate it using your secret and your clock. These need not be sent as 3 parameters; they can be concatenated into one string user|timestamp|token.
Register your application with SLI. SLI grants a unique client ID and a client secret that enables your application to authenticate to the SLI API. You must also register the redirect URI of your application for use in authentication and authorization flows.
Enable your application with specific education organizations so that the application can be approved for use in those districts.
Configure and implement the appropriate OAuth 2.0 authentication and authorization flow in your application, which includes managing sessions and authorization timeouts.

Cookie based SSO

How can I implement a cookie based single sign on without a sso server?
I would to share the user logged in across multiple applications using
only a cookie on the browser.
In my mind it's working like this:
user logs in an application
the application verifies the credentials and then it setting up a cookie on
the browser storing the username (that could be coded with a private key)
if the user opens another application, it searches the cookie and reads
the username on the value (using the key for decode the string)
In this solution a user may see the browser cookie (of a another user)
and take the string codified of the username. Then he could adding it on
an own cookie (no good!).
There's some secure way to do this? With a timestamp based control or
something like this?
Thanks in advance.
Bye
P.S.
I know that my english isn't very well.. sorry for this!
This is impossible. Cookies are unique to each domain, and one domain cannot read another domain's cookies.
I think the answer comes a little late, but maybe I can help someone.
You can have a cookie / localStorage in an intermediate domain connected to the home page using an iframe
1) Login
The login form in any of your domains deposits the identification token in a cookie on sso.domain.com by an event (postMessage)
2) Verification
domain1 and domain2 include a iframe pointing to sso.domain.com, which reads the token and notifies the home page
To simplify development, we have released recently a cross domain SSO with JWT at https://github.com/Aralink/ssojwt
There is a simple solution without using an sso server, but not with 1 common cookie, as we know that cookie's are not shared between domains.
When the user authenticates on site-a.com, you set a cookie on site-a.com domain. Then on site-b.com, you link a dynamic javascript from site-a.com, generated by server side script (php, etc) who has access to the created cookie, and then copy the same cookie on site-b.com on the client-side using js. Now both sites have the same cookie, without the need of asking the user to re-login.
You may encrypt/encode the cookie value using a method that both site-a and site-b knows how to decode, so that site-b will be able to validate his cookie copy. Use a common shared secret that without it will be impossible to encode or decode.
You see that on the 1st page load of site-b.com, the cookie is not present, therefore if you see necessary, you may want to do a page reload after setting the cookie.
I have done something similar. There is a PHP application where the user logs in, the system contact a web service and then the service checks the user's credentials on the Active Directory. When the user is authenticated, his PHP session is stored in the DB. Another web application can read the PHP session from the cookies and uery a web service in the PHP applicaiton, the PHP application check the session in the database and return the user id. In this way I have a SSO using SOA.
Do not rely on the user id stored in the browser, is a security error, at least encrypt the id.
The best solution would be to put the login form and session storage in the same application, then this application can provide services to other applications.
And use HTTPS for the kind of infomation exchange.
The cookies can be read only if the belongs to the same domain, for instance:
intranet.example.com
crm.example.com
example.com/erp
You can access cookies across subdomains, but I do not think using browser cookies is a great solution. You really don't need a "SSO server" to implement a single sign-on. It is fairly easy to come up with a payload that both applications recognize. I have seen custom SSO solutions that transmit the payload using XML over HTTPS.
Here is a solution (which will hopefully get heavily scrutinized by security gurus on here):
Have each domain store user data in a similar cookie, and when a user want to jump from one domain to another without authenticating themselves on the new domain, provide a "jumplink" with an encrypted token in the query string. The new domain would decrypt the cookie, and figure out who the user is, then issue them a new cookie for that domain. You would want the "jumplink" to have a very short expiration date, so I would not generate them right into the page, but generate links to a "jumplink" generator and re-director.
This might not be necessary, but the receiving page for the "jumplink" could make a web service call back to the originating domain, to verify the authenticity of the encrypted token and the whether it's expired.
I think this solution would be susceptible to man-in-the-middle attacks (not sure if it would be more so than other auth mechanisms which are currently popular), but you could incorporate a client MAC address and IP address into the encrypted token for extra security.