Wrapping my old-fashioned head around OAuth....
Aside from the request/response mechanics and the Authorize / Authenticate round trips (which I think I underdstand) I am struggling with mapping my MyUser object (whatever that may contain) to an OAuth token, if (actually when, not if) the user kills any cookies (encrypted or otherwise) I may have dropped on the browser.
I get MyUser info at the original Login (call it 'registration' for my site) but now MyUser comes back, all cookies are gone so he is just 'user'. Fair enough, user has to do an OAuth login again, but now I have no way of associating the new Token / Secret with MyUser data.
What am I missing?
--- edit Aug 2/2012 -----
Let me restate this (I am pretty sure I am being thick about this but guess thats what here is for):
As pointed out in Replies, each OAuth provider has their own mechanism. We can navigate those and get back an access Token for the user.
Lets say Hero registers on my site using Facebook. FB returns his FB UserID and Name along with the Access Token. We are clever enough to request and get his FB Email, and we ask him some other registration q's before letting him in. Then we save this in our datastore (linked to our own User record):
OurUserId : 1234
oAuthProviderName : Facebook
oAUthProviderUserId: xxxxx
oAuthProviderUserEmail: hero#mlb.com
oAuthProviderUserName: iBeHero
oAuthToken: entracingly-unique-string-of-goop
oAuthSecret: moredata
.... etc.
and set a cookie to identify him as our user# 1234.
Now Hero goes away, kills his cookies for some reason, and then comes back to us.
Now he decides to Log In with Twitter. I have no cookie so I don't know who he is, and we go through the process again.
To me he looks like a new user so once Twitter sends me a Token I start asking him Registration questions, clearly not right.
Turns out Twitter doesn't return an Email address so I can't match that, and even if they did (I think almost everyone else does) Hero likley has more than one Email.
It seems to me that the only tie I have between the two (or however many) logins is whatever cookies I set that have not been deleted.
Are we saying that the entire OAuth2.0 mechanism hangs on this? I can't belive that is right, but don't see another way, so I must be missing something , yes?
If you're using OAuth as a login mechanism as well, then make sure whichever provider you're talking to has some way of returning back a stable ID for a user. That ID is the key you'd use for looking up the user in your DB.
Different providers have different ways of doing this. For Google, details on how to do authentication with OAuth 2.0 are here. For Twitter, they use OAuth 1.0 and return the user ID when exchanging the code for an access token. Facebook has its own way of doing it as well.
Related
I am using django JWT for permission and rest_framwork.
there is one question. if one user uploads one post and wants to modify/delete post OR wants to change own's profile,
definitely user requests restAPI. and in the http(s) request maybe there is some information about user,
like "localhost:8000/data/change/userid/" OR exists in post body.
point is i think if someone(like hackers) catch others id(or ID number) and pretending them
server doesn't know that who is real owner does it?
how can i protect or encrpt?
Since you are using JWT, you should have a token for every request with JWT permission. So without the token, the whole system wouldn't work. As far as I can understand, you are assuming that somebody in the middle would grab some ID related to the user but that doesn't important because he wouldn't enter the system only by id!
Furthermore, whenever you are using this under HTTPS, the token is safe too. (because no one can in the middle grab it without encryption )
We have React Native app that uses Cognito for authentication. We would like to prevent the same user ID from logging in simultaneously from multiple devices.
We were hopefully that we could use a Cognito pre-authentication trigger for this. Unfortunately it seems that we can't just call globalSignOut for the user since that wouldn't invalidate tokens that have already been issued and are currently active (see https://github.com/amazon-archives/amazon-cognito-identity-js/issues/21#issuecomment-331472144).
The other idea was to reject the login if the user is logged in elsewhere. But we can't see a reliable way to tell whether the user is already logged in. We can see if there are valid tokens issued for that user but not if they are currently associated with an active session.
We also thought of maintaining our own DB of active sessions but there is no sign-out trigger so we wouldn't know when to remove a session from the DB.
You can use a token authentication system,
Issue a brand new token for each login, and check for available tokens.
if any token is available for the user that means He/She is logged in some other device, for this case you can prompt user that You are logged in other device.. are you sure you want to log out from that device ? and after clicking yes, you can clear all tokens for that user. And issue a brand new token.
AUTO LOGOUT : this token should be passed all over the back-end i.e. in headers of each and every API call token should be there... and should be checked before doing anything in back-end. if token is not available then throw 401. In your app if any API throws 401 then it means user is UNAUTHORIZED and should be logged out.
or
your app should be listening to one socket that responds to log out when it receives a message of same. so whenever your user logs in, a logout message will be passed across sockets and appropriate device with some token id or unique id will get that message and will log out a particular user from all other devices.
or
have a notification receiver which will be used to log out whenever necessary same as socket.
Reading the link you provided the API token / session system seems being faulty by design since long time already.
So without an own token-system inside cognito you won't have reliable results probably, at least in the current state of the system (as the repository is archived it won't be developed further by the owner).
What I propose is an own field in the database-table for users where each login is honored with an own token. A second own field in the same table with a timestamp, where the last access is saved.
If last access is older than a predefined time of 30, 60 or 120 minutes any user gets logged out.
If the last access is younger than the time-limit then the login-mask has to provide a random access token which is compared with that in the database:
- if the access-token in the database is too old for an active session, or just no access-token is stored, then access can be granted which means login is successful.
- the comparison of the current time with the time-stamp saved in the database is for cases where users never have been logged out by purpose but just by being disconnected or passive. I think this case will happen regularly, so it's no exception.
- logging out by click on a button should destroy the access-token in the database, so that the user can immediately login from any device, even from another one then before.
- if there exists a valid access-token in the database then no new access will be granted and the user should get shown a message that he has to sign out first at another login.
- The access-token could be stored together with a third own field for the session-id to make it more reliable and safe. On logout that session-token-field can be cleared too. The session-token can be copied from the global session if required to be saved in the user-record.
- Any checks are only done on login, tokens never have to be included on every page.
- On active logout the token(s) have to be destroyed to allow a direct login again, else the users had to wait till the max. age of the time-limit is reached to login again - at least on another device then before.
As the login itself is currently done independent from the check that has to be implemented, it would be possible to leave the new access-token completely away but use only the session-id as that differs on any device and browser. But perhaps there exists a situation where one of session-id and access-token can change but the other one not - I don't think so but perhaps I missed something in my considerations.
If you provide the access-token on every page like proposed by #Jadeep Galani or in a cookie - beside the corresponding check - you also can offer a button to sign out from all devices. This would enable the users to change login any time even without logging out at the last used device. Without access-token on every page or in a cookie this general logout-function solution is not possible as else access is only checked on login but not on all pages.
A general question is if it's still worth it to rely on the buggy cognito for login or just replace it completely by an own solution. You even could implement the desired authentication in your site in form of a wrapper-class and the concrete login-system could be replaced without changing that implementation.
You can use the UUID of the device to identify whether it is the same user. Add a UUID to each request header to record it in the DB, and then you can do what you want.
We are having a facebook App we have detected some abusive users so we want to stop them from logging into our app, Any thoughts? There are examples given but Fb docs say those api's are deprecated now
You could just detect them on your own and set a flag in your database. They will still be able to use Facebook Login, but they will not be able to do anything in your App if they are flagged.
Either way, i did some Google research and found out that it may be possible with a simple POST (or DELETE) request to the /app-id/banned endpoint:
BAN
https://graph.facebook.com/{app-id}/banned
POST parameters:
access_token (A simple App Access Token)
uid (comma separated list of user IDs)
UNBAN
https://graph.facebook.com/{app-id}/banned/{user-id}
DELETE request, only access_token as parameter
It is not really documented though, but easy to test.
I'm using server side authentication for Facebook detailed on this page.
https://developers.facebook.com/docs/howtos/login/server-side-login/#step5
I'm asking for extended permissions like user_birthday and if the user accepts, I get the code
YOUR_REDIRECT_URI?
state=YOUR_STATE_VALUE
&code=CODE_GENERATED_BY_FACEBOOK
But if let's say the user declined to provide birthday, I still want to proceed when I get this url
YOUR_REDIRECT_URI?
error_reason=user_denied
&error=access_denied
&error_description=The+user+denied+your+request.
&state=YOUR_STATE_VALUE
Does anyone know how to get the code under that scenario or do I have to ask the user to signin again but this time not asking for additional permissions?
Cheers,
Steve
Does anyone know how to get the code under that scenario or do I have to ask the user to signin again but this time not asking for additional permissions?
There are two scenarios here:
You are asking the user to connect to your app for the first time. At this point, they can not decline giving you user_birthday permission solely (since it’s a basic and not an extended permission) – they either connect to your app, or they don’t.
The user has connected to your app before, and now you are asking for user_birthday permission. If the user declines that, that will lead to the error_reason=user_denied – and then you will not get a code parameter.
In the 2nd scenario, when using the server-side flow, asking the user again (maybe with a reduced set of permissions) is the only way to go – unless you have already gotten an access token before. That will not get invalidated – but it will obviously only contain permissions already given before.
(If the user connected to your app before, you can just call the Auth dialog with no scope parameter at all – in that case Facebook will redirect straight back to your app with a code parameter. Or you could get the token beforehand client-side, for example by calling FB.getLoginStatus.)
I'm playing around with Facebook Connect, trying to use Facebook as the means or authentication on my site. Currently my workflow looks something like this:
Go to URL
Server checks cookies for AccessToken
If AccessToken exists, automatically fill in user's name/profile picture in comment box, and leave AccessToken in hidden input
send page down to client
on submit, verify access token (which was submitted with the rest of the form) is a valid access token for a real person. If so, add comment to Database
refresh page to display new data
if no access token, replace user's name/profile picture with <fb:login-button>, along with the required <script>s.
send page down to client
When user authorizes page/logs into facebook, refresh page
(go back to top, except this time the access token should exist)
So I have a few questions:
Is this secure? I was thinking of ways i would be able to do without the double authentication with Facebook (checking once on page-generation and checking again on comment-submission), and I could not figure any other way short of maintaining my own session-state with each client. Is that worth doing?
Does the access token expire when i log out of Facebook? I'm thinking it should, but it seems I can continue to use the same access token to grab data (i.e. name, url, etc.) after I manually go to Facebook and log myself out. Is it because I'm only asking for public information, and only more intrusive permissions expire on logout?
Given that each person who wants to do something has to provide a unique token from Facebook, this should have the side effect of blocking CSRF, since every action can be traced to a valid Facebook account. Is that right?
Why don't you just use the Facebook Javascript SDK to detect if they're currently logged into Facebook? This will also make the access token available in Javascript so you can make client-side calls to the API.
You can access the same access token server side via the session cookie set by Facebook also.
I can't answer all of your questions but I can tell you that having the access token in a hidden field on your page is risky from a policy perspective, especially if your page can be read by any third-party code such as Google Analytics or AdSense. Facebook will nail you for this as it is leaking user identifying data to third parties. The Facebook userid is in the access token in plain text. Facebook has automated processes that scan for this stuff and will auto-ban your app if it is leaking userids to third parties.