authorization: what is the flow for non-first time user? - c#

I have a site (still on localhsot).
I want to authorize the user against Google and get permission to gmail scope.
I get a requestToken
Authorize it
Save requestToken from the queryString into a cookie (?)
(I don't have accessToken by now)
Upgrade it to accessToken
Then what?
I thought to save requestToken and accessToken in the DB with some user guid (?)
Are they both parmenent and uniqe?
Will it help next time to avoid the Upgrade it to accessToken
When the user come back for the second time - how will I retrieve its access token?

You will have to store the access token with the user data, yes. Then you will set the Forms Authorization cookie as normal against their username or id.
When they come back a second time, if they still have the cookie, then they will be signed in as normal.
If their cookie has expired, ask them to log in with their chosen provider (Google) and retrieve the token again. You will then have to search the data to see if any users have that token already, and if they do, log that user in as normal like you do the first time.
If they log in with a different provider, they will get a different token and will effectively be seen as a different user - how you handle this is a separate issue.

Related

Refresh identity token from client from code

I am using the fine-uploader with an asp.net mvc backend to upload files directly to an azure blob-storage. The asp.net-server works as the azure-signature-endpoint(sas). This is all secured with an identityserver3 and here comes the problem: The identity_tokens lifetime is set to 5 minutes(as default). And I want the SAS endpoint to be only called authorized. So a user can only access its own data. But after I have the upload running for the set 5 minutes, it breaks. Of course, because it is not authorized and it returns the login-page from the identity-server(which the fine-uploader, of course, can't handle).
It would be easy to solve this problem, by either setting the lifetime from the token to something higher(but this is unreliable as the upload could take hours or days), or disable the lifetime(yeah would work. But I guess the lifetime has a reason to exist).
So my 2 ideas would be:
to just authorize the user once(when he starts the download)
or to refresh the token by code every time the signature gets generated.
First approach
Can I just set a boolean like user is authorized and if this boolean is set just skip authorization and just return the signature or how could I achieve this
Second approach
How would I do this?
Don't use the id token for API access, an instead use access token. Access tokens are for resources (APIs), whilst id_tokens are purely for authentication. The id_token is only meant to be used to provide the RP with means of knowing who the user is - hence no need for long time span. It's only there for converting into a user session (cookie/principal).
With access tokens you have several approaches for keeping a valid token at a client; either by fetching new ones using the client credentials flow or by using the refresh token approach.
I believe there are samples of both in the samples repo of IdentityServer.
Samples repo link

Asp. Net 5. Jwt tokens revocation

I am using jwt tokens middleware and Asp.Net.OpenIdConnect.Server in my app. In fact, it works fine. But I am confused in one thing. If I use tokens, I can not immediately grant new claims or ban my users. For example. I give my user access token, which expires through 2 days, and refresh token, which expires through 2 weeks. Then I give to this user admin rights. But he will know about this only through 2 days, when his current access token expires, and auth server will give him new token, using refresh token. How can I give him new rights immediately, on the next request?
I understand, that I need to check database for every request, and give to user new access token, if needed . But where should I do it in aspnet 5? Maybe there are some good practices for such thing?
One way doing it is to put a unique identifier into your claims, which you can query to see if it's still valid. You can use the memory cache to store it or some distributed memory cache such as Redis, so you don't have to hit the database every time.
When you ban the user or add a token, you mark this token as invalid by removing it from the cache. Each time you the user refreshes the token, it you should create a new unique id inside the token.

Restrict concurrent login - ASP.NET Identity

I am trying to only allow a user account to be logged in, only once at the same time.
E.g. User logs in via the browser on their computer, now they cant login at the same time on their phone as they are already logged in.
I can add a bool property to my user entity, that I can update when the user logs in and logs out.
However, I am using SlidingExpiration on the authentication cookie, therefore when the cookie expires it doesn't update my user property to say they are now logged out.
ExpireTimeSpan = <time period>,
SlidingExpiration = true,
Are there any better approach to restricting concurrent login?
Thanks
Can you generate a Token at log in and store it in Data base?
Then, check every time if the token matches with the one provided by user.
If he does log in in another device, the token will be overwritten and won't match with the first one, so the first session will become invalid.
EDIT:
As you asked in a comment, it doesn't block a user to perform a second log in in another device concurrently, it only invalidates the previous sessions.
Avoiding a second log in requires more job and isn't as safe as the method shown above.
Imagine that the user closes the browser without performing a log out... It will block the session.
An approximation of what you want will be adding the time parameter to your log in (adding it into the data base too, and updating the field on every user's action).
Then show the message of "you can't log in twice" if the token doesn't matches and the time span is not far enough (i.e. 5 minutes). But in my example you need to show a "your session expired" if the token has changed anyway.
"The idea is very simple every time the user logged in you have to generate random token , then you should save that token in the database and in session or if you are using Microsoft form authentication you can save it in the ticket, then each time the user request a page you’ll check if the session token is same as database token , if not kick him out!"
http://engthunder.wordpress.com/2011/10/19/preventing-multiple-user-from-logging-in-using-the-same-username-single-user-login-at-a-time/

ASP.Net Identity Identity.IsAuthenticated remains true, even after deleting user

I have implemented ASP.Net Identity after following the sample code here:
https://github.com/rustd/AspnetIdentitySample
In my implementation I check if a user is authenticated - this is called from a FilterAttribute on my MVC Controllers; the idea is i want to confirm they are still auth'ed before serving up the page.
So in my filter, the following code eventually gets called:
_authenticationManager.User.Identity.IsAuthenticated;
_authenticationManager is here:
private IAuthenticationManager _authenticationManager
{
get
{
return _httpContext.GetOwinContext().Authentication;
}
}
The _httpContext is passed into the constructor of my identityProvider class.
Now - once I have logged in, _authenticationManager.User.Identity.IsAuthenticated; returns true as expected.
However, during development, i dumped and re-seeded my database, without adding a user. So effectively, I have deleted the IdentityUser - yet _authenticationManager.User.Identity.IsAuthenticated; STILL returns true
any idea why this is? I can only assume it's somehow checking a cookie, rather than actually looking at the DB. is this correct?
Or have i messed up my implementation.....
This does not make IsAuthenticated a security hole. Let's look at the actual authentication process.
You setup some stuff in your web.config around where the login page is, how long the login is good for and whether or not to use sliding expiration (should the time be extended if the user is active on your site)
User comes to your site, enters their username and password.
That information is posted to your server. You take that information, verify that it is correct (authenticate). If it is correct, the server then issues an encrypted cookie known as the FormsAuthenticationTicket Note - this could have a different name in the new Identity stuff, but the same principle.
The cookie's contents includes items such as the user name and expiration date of the login.
On each request, the server looks at the cookie collection for the authentication cookie. If found, it decrypts it, reads the values and determines if this is still a valid cookie (expiration time). Once it has the user information from the cookie, the server can use this information to determine if the user is authorized for the resource requested (look up by username).
5a. If the cookie is not present, or has expired, then the user is redirected back to the login page.
6.When the user logs out, the cookie is deleted from the cookie collection. Now, if the user tries to go to a resource that is for authorized users only, then the server ends up at 5a above.
So, in your case, you deleted a user manually. This does not change the fact that this user has previously been authenticated with a still valid cookie. Therefore, IsAuthenticated is returning the expected value. The user has authenticated before you changed his user status. IsAuthenticated does not mean, is this user still valid in my database.
If you are going to be running a site where you are constantly deleting/deactivating users, then override the OnRequestAuthorization method of the AuthorizeAttribute to look and see if the user is actually still in the database. Also, note that if the username is not present (because you deleted it), then any look ups for role / userId will fail. You can catch that exception / failure and return the property unauthorized response.

Session lost after first Twitter OAuth request

Using ASP.NET MVC, sessions are stored in SQL database (never had a problem with them, and didn't use web farm). Using also Twitterizer2 library. Using Firefox.
First request, no browser instances is opened. Browser instance is started.
We have simple form "Publish on twitter" and submit button Share.
When Share is clicked we store message in Session and redirect to Twitter's OAuth authentication (on POST submit).
We authenticate OK and return to our Action and before posting to Twitter we check if message is stored in Session (and it isn't! - it is lost immediately after Twitter redirection)
When we try another messsage Share it is now working (Session).
We solved it using a Cookie but we don't have a clue while we lost Session (first time) after returning from Twitter.
Any deas?
I'd like to ask how did you maintained the session without cookie the first time?
I think the problem can be of the cookie set process. I also experienced similar problem before a couple of weeks.
The problem was that when I make request for REQUEST token, this request is internal HTTP request (not via user browser). As a response to this request I get REQUEST token and then set it in the user session.
$token = getRequestToken();
$_SESSION['token'] = $token;
However, if the user just came to my site for first time without a session, he does not have a session cookie to sent me. Internally at the web site I have created a session for him, and stored the token inside it, but then instead of sending him response with cookie headers included, so that he "accepts" my session, I make redirect to the provider authorize endpoint. This way, the user does not get the session cookie, and when he is returned back, he is like a new user for my site.
This is the flow of the process that happened to me:
create user session in the database
setcookie(usersession) // add headers to the eventual response
get request token
set the token in the session
redirect the user (user does not receive the session cookie)
user goes to authorization point
user returns, but he is a new user for me
I'd be interested to know if you had similar problem :)
Best regards
check the request and callback domain are the same
i.e. you are making request for oauth from localhost and callback to 127.0.0.1

Categories