We're considering a few options for single-signon between our Django web application (we'll call it Website 1) and another specific website (Website 2). Our two top priorities are:
Ease of implementation/maintenance.
Avoiding the complication of our login process (our audience is not technically savvy at all). In other words, I don't want them to even know what OpenID is. They know to use their credentials from Website 2, though.
There are tons of Django apps for OpenID, but we don't want our users selecting their provider (we want to force them to use their "Website 2" credentials). This is my primary concern: Can I hardcode the provider so they are always using "Website 2" as the authority?
Here's what my research so far seems to think would be the flow:
User goes to the login page. We either display a button for them to click on to login, or
we just say "We're going to redirect you to Site X for authentication" and do so after a few seconds.
User gets redirected to Website 2. They enter their credentials and are redirected back to us.
The user doesn't know/care what just happened, and we have something simple to launch quickly.
Am I on the right track? Is this even possible? Do you see any caveats?
Related
I don't believe I need OAuth
Then again, what do I know
All I want to do is take someone's credit card information and charge them. I am not accessing other people's QuickBooks accounts (only my own) and I am not trying to access any other personal information other than what they input into my form. For this reason it seems absolutely asinine to think that I'd have to redirect them to intuit.com and force them through an OAuth prompt (what account would they even be authorizing? They probably don't have a QuickBooks account)
I've spent the last hour reading through QuickBook's API documentation and I've run in circles and found the whole thing utterly confusing. Every page which references a particular API endpoint makes no mention of authentication -- only the headers, query parameters, and request body that are expected. The API explorer does not show any form of authentication in their examples:
No basic auth header, nothing in the request body with an API token,.. nothing
Checking the console while hitting submit isn't any more helpful. The request gets sent to their back-end server where it does the real request:
It even includes "apikey", "apisecret", and "oauth" attributes in the body which are all empty -- it acts like the endpoint doesn't even NEED authentication.
Out of dumb curiosity I tried making the request with no authentication to see what would happen:
401 Not Authorized. So some authentication is needed. I continued to scour the docs and turned up nothing but page after page linking me back to OAuth and saying that I need to set up OAuth. Why do I need to set up OAuth to take a credit card number that was given to me and hand it to QuickBooks?
I even tried looking at their sample app. The "take the code for a test drive" (https://developer.intuit.com/v2/ui#/emulator?workflow=ecommerce) was utterly worthless. It only gave me some pseudo-code with zero idea for how to handle authentication:
I even looked at the actual code and don't see anywhere that they provide an API key or secret key.
I'm pretty much ripping my hair out at this point, so I think I need someone with experience to point me in the right direction.
I don't believe I need OAuth
You do.
For this reason it seems absolutely asinine to think that I'd have to redirect them to intuit.com and force them through an OAuth prompt
You misunderstand what OAuth is, and how it's used.
OAuth is used to get YOUR auth tokens so that YOUR COMPANY can authenticate to Intuit and identify itself so you can charge customer credit cards. YOU are redirected to Intuit's website to authenticate ONCE, and ONCE ONLY, and then NEVER AGAIN.
You store the tokens you get back from the one-time OAuth pop-up window process, and use those for all future HTTPS requests.
The end-user (i.e. your customer) is NOT redirected.
If you're familiar/used to something like Authorize.net or other web services, where you open a web browser and go to a website and copy a secret key/API token into your code... this is the exact same process except instead of you logging in and manually copy/pasting an API token/key, you're logging in and the OAuth process automatically gives you the API token/key programatically.
I'm working on an internal website for the company I work for. The website will be only available to company staff. We use Google Apps for Business, so we would like authentication to be done using our google accounts.
I've gone through 'google sign in' samples from here: https://developers.google.com/+/
It works, but the problem we run into is that it requires the user to sign up to Google+. This is a speed bump we would prefer not to have.
Are there any ways around this? Thanks.
It shouldn't be too hard to roll your own sign in using the lower levels of Oauth, eg 'email' scope. It's hard to give a more specific answer because it depends on your architecture (eg. are you predominantly server-side or client-side) and what kind of session do you want to create by the sign in process. For example, if you are client/REST based, you probably don't want any session at all as REST encourages statelessness. On the other hand, if you are more web based, serving static pages, you will want a session.
In simple terms, you will be doing something that generates an access token, and then processing that access token to determine the email address (or Google ID) of the person who created it. You will then establish some sort of session (eg. using session cookies) that identifies future requests from that user.
Feel free to add some more detail to your architecture and I'll try to finesse the answer.
For simple http servlet sessions, it will be something like.
User requests a protected page
servlet detects that there is no session and/or session has no authenticated user
servlet redirects to an Oauth page to request an access code. something like
https://accounts.google.com/o/oauth2/auth?redirect_uri=xxx&response_type=code&client_id=zz&approval_prompt=auto&scope=email
NB research the exact URL, don't rely on this to be exact
If the user isn't logged on, he'll be prompted; if he has multiple logins, he'll be prompted; if he hasn't yet granted email access, he'll be prompted. If none of these conditions are met (the normal case) he won't see anything.
Browser will redirect to the redirect_uri, carrying an access token (or an auth code if this is the first time the user has used the app)
Post the token to the Google userinfo endpoint, and you will receive a decode containing the email address
Store the email into a session object (or retrieve your own user object and store that)
redirect back to the originally requested page. You can use the OAuth state parameter to pass that around
et voila. all future page requests from that user will be within a session containing some user identification.
NB This is just an outline and I may even have missed a step. You will still need to do your own OAuth research.
Apparently not:
(..) if a Google user who has not upgraded to a Google+ account clicks
on the Sign in with Google+ button, the same consent dialog that opens
will take the user into an account upgrade flow.
Weirdly the docs for OAuth2 states:
Google+ Sign-In works for all users with a Google account, whether or
not they have upgraded to Google+.
I am thinking of tying in a Facebook JavaScript-based application with an existing website that has it's own user accounts, but have a question about a specific user situation.
The website is run almost 100% of the time from 'shared' computers, like those found in a career center. User A comes to my website, signs into the site and then authorizes the Facebook app, which stores their session in the browser, along with, effectively, signing them into Facebook.com.
User A now leaves my application by signing out of my site - but not closing the browser.
User B arrives, logs into my site with their login, but the Facebook session is still active (due to the browser staying open), so any FB app integrations I've included will show as if it is still user A, correct?
So the question is, what are the recommended ways to deal with this? Two options come to mind:
When the user signs out of my website, I fire an FB.logout call, so that all of the sessions are killed. Pros - I can ensure that user's signing into the site will not have old sessions hanging around. Cons - a user who is returning shortly after leaving will have to re-login to FB as well as my site to see the FB integrations - I'd love to avoid the user ALWAYS having to do two logins. Secondly, forcing the FB.logout when they leave my site kills any active sessions they have at facebook.com, which makes for a bad user experience as they would not 'get' why logging out of my site has anything to do with facebook.com, and will then have to re-signin to facebook.com.
The second option would be that when the user authorizes the FB app, I take their member ID and store that locally and persistently (database). Then, when a user returns to the site and signs in, I check their FB auth status, and if logged in to FB, pull their member ID and check it against the one I have stored locally. If they match, I have the correct user, if not, I do FB.logout and have them sign in to FB. Pros - this should ensure I always have the correct user to the site. Cons - not sure if getting, storing the member ID is feasible.
Any suggestions or pointers to the 'best practice' when it comes to ensuring that the current user is indeed the one associated with the FB account, specifically in this 'shared computing' situation where sessions may overlap?
Thanks
The second option looks to me to be the better choice. You can indeed store the users facebook id. By storing it locally i'm assuming you are talking using a cookie; however storing in a database is just as feasible.
Facebook user id's should be stored with a BIGINT(20) data type - such are the recommendations from facebook.
Taken from the user section of the facebook api refrence :
Looks like they changed their recomendations...
Is it possible to limit the users who can sign in with open id on my site. I have clients that I want to give access to a client area on my website. I don't want anyone with a open id to be able to login just my clients. Is this possible?
One way to do this would be to create a "sign up" form to validate the user. Part of the sign up process would be to associate your OpenID. You can then leave the newly created account in a "pending" mode to be approved by an admin. (note: if you have a different way of adding the clients, you would use that method.)
Basically you would create a profile for a user the same way you would in any other application, except you would replace the UserName / Password portion with OpenID.
OpenID is made for authentification, not for authorization. I am sure, you could make it work (*), however you must keep in mind that OpenID has not been made for this sort of task.
If you want to do it, you must probably restrict the set of allowed OpenID providers to prevent a malicious provider to hand faked/bogus identity URLs to your application (consumer).
(*) how, depends on where you want to enforce the restriction (web server, web framework, etc.)
I'd like to create a piece of code that can be embedded on many different websites (widget).
Is there any way that my code can identify a user without them logging in? I.e, can I use any of the established identity mechanisms floating around the web to reliably identify them across instances of this widget?
I don't need to (nor should I be able to) tap into any information about this user, just identify them.
The websites will be heterogeneous; there's no guarantee that they will have any common aspects, so the widget code needs to be entirely self contained.
What you want to do is what cookies were invented for. But browsers have gotten wise to people being tracked without their permission, and now limit 3rd party cookies.
The Electronic Frontier Foundation recently put up a proof of concept for uniquely identifying a visitor based on attributes of their browser. It's uses things things like:
User-Agent string
http-accept values
timezone
screen resolution and color depth
the installed plugins
if cookies are enabled
It's not guaranteed to be unique, but my browser certainly is, and it will get you on your way to doing the bad things that people don't like.
OpenID is sort of a SSO for the whole internet, yet they still have to sign in to OpenID. Other than that, I can't think of a solution.
I would suggest Open-ID rather than some workaround like this, but if you don't like that solution you might consider something like this:
You can use a cookie from a single domain, then use that domain to redirect to the correct site adding user-id as a parameter or part of the URL-path
For instance a link to add a personal widget on the foo.com -site, could look something like:
http://bar.com/addwidget1?backtoo=http://foo.com/main/
bar.com would own the cookie, change the user preferences and then add user-id to the back-link before re-directing:
foo.com/user-id/
Issues with this approach includes
You need to rewrite every page dynamicly with the user-id.
It's a bit clumsy I think
You can't fully take advantage of web-caches around the net.
The user might loose their cookie.
Benefits
No login
Since you redirect a lot you get stats on the users movement across your sites.
Sounds like you want to implement a Single Sign On framework. Basically when you first see the user, if you don't know them, you redirect them to the single sign on server. Wich authenticates them and redirects them back to you with a authentication token. You verify the authentication token with a web service call to the SSO server. Ff it is valid then you mark that user as signed on.
EDIT
So thinking about it more and reading tovare's answer and your comments. Why not create some javascript code that works like an google ads? You put the javascript on the page and it does an a request to your central tracking server using a dynamic iframe.
Have your tracking server return an image tag with src of the unique id (its own session id) embedded.
<img src=contentserver.com/track.php?id=12345668>
The content server has a server side script (track.php above) that maps its local session id to the unique id received from the tracking server.
The unique id stays the same across all sites.
Edit2
Instead of using an image, use the javascript trick. The content server just requests a javascript file from the tracking server. but the file is a dynamic one generated on the server side. it returns a generated javascript function called unique_id() it returns the unique id from the tracking server. Call the track.php using ajax to determine if this is a unique user.
Use OpenID, or a simplified variant, with your own site as the identity provider. Redirect the user to your identifier site which sets or checks a cookie, then redirect the user back with the user's identity, which was indicated by the cookie, added as a URL argument.
Your identifier site can be an OpenID identity provider which doesn't require any user interaction to authenticate. The sites which receive this identity are probably not OpenID consumers, since they don't offer the user a choice of providers. You can probably do away with some of the signing required by OpenID if your cookie and identifier are signed.
Facebook provides something similar; a site can find the Facebook identity of a user (assuming the user has one) without any action on the user's part.