Keycloak Action Tokens: How to invalidate user's previous action when they request multiple (e.g. Reset Password) - authentication

I want to be able to invalidate any action token for a user within an authentication flow.
The scenario is the user sends a reset password and receives an email with an associated action token. The user then sends another reset password and gets another email with a different action token associated. For the length of the first action token expiry time the user can utilise the links in both emails - however I'd like to be able to identify within my custom reset password authentication flow that the user is requesting a duplicate action request and invalidate their earlier action token(s) so that only their latest reset password link works.
I've been looking at the below objects but had no luck finding an action token store associated with all the user's activity rather than just their current authenticated session.
AuthenticationFlowContext context;
List<UserSessionModel> sessions = context.getSession().sessions().getUserSessions(context.getRealm(), user);
RootAuthenticationSessionModel parentSessions = context.getAuthenticationSession().getParentSession();
ActionTokenStoreProvider actionTokenStore = session.getProvider(ActionTokenStoreProvider.class);
Thanks in advance.

I've resolved this by maintaining a Table of users and action tokens per flow. This means when the user initiates a new action flow I can grab the previous token if still valid and use the ActionTokenStoreProvider to invalidate it replacing it with the new token. I am still hoping keycloak has some internal mechanism to manage this rather than my own custom code. Drop a solution if you know of this!

Related

How to handle expired auth tokens in Xamarin MobileServiceClient?

I am using client-flow authentication in Xamarin.Forms and am trying to figure out how to handle when an authentication token expires.
My Code:
Upon initial login, the user logs in with the native Facebook SDK and I pass the access_token to MobileServiceClient to get back an authenticated user.
var user = await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token).ConfigureAwait(false);
I then save the user's UserId and MobileServiceAuthenticationToken in local settings (using the Xam.Plugins.Settings plugin).
The next time the user opens the app, I set the user from settings and skip manual login:
if (!string.IsNullOrWhiteSpace(Settings.AuthToken) && !string.IsNullOrWhiteSpace(Settings.UserId))
{
client.CurrentUser = new MobileServiceUser(Settings.UserId);
client.CurrentUser.MobileServiceAuthenticationToken = Settings.AuthToken;
}
My Question:
This works great. However, I know that the MobileServiceAuthenticationToken has an expiration on it. What will happen in my app when the expiration date is reached? How do I refresh the token without requiring the user to re-log-in to Facebook? I have tried the MobileServiceClient's RefreshUserAsync() method, but I get the following exception:
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: Refresh failed with a 400 Bad Request error. The identity provider does not support refresh, or the user is not logged in with sufficient permission.
Is there a way to test this? (since the token expiration is 3 months from now.) Thanks for the help!
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: Refresh failed with a 400 Bad Request error. The identity provider does not support refresh, or the user is not logged in with sufficient permission.
Since you are using client-flow authentication, you could not use RefreshUserAsync() for refreshing the MobileServiceAuthenticationToken. Your mobile backend does not cache the related access_token and refresh_token for renewing the authentication Token.
Is there a way to test this? (since the token expiration is 3 months from now.) Thanks for the help!
AFAIK, the MobileServiceAuthenticationToken expiration is one hour by default, you could use https://jwt.io/ to decode your token and check the exp property, then use https://www.epochconverter.com/ to convert your timestamp to human date.
For your requirement, you could follow adrian hall's blog about Caching Tokens and refer to the IsTokenExpired method for decode your authenticationToken and check the exp, then manually renew the authenticationToken.
Per my understanding, there are two approaches for you to achieve your purpose:
You need to cache the facebook access_token in your mobile client side, after you manually checked the authenticationToken and found that it expired, then you could manually execute the following code for renewing the token and explicitly update your local cache.
var user = await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token).ConfigureAwait(false);
Note: Your facebook access_token has the Expiration Date, so if your access_token expired, then you need to force the user to log into Facebook again before acquiring the new authenticationToken.
Or you could build your custom endpoint for refreshing the authenticationToken and explicitly set a long lifetime for your new authenticationToken, details you could follow this similar issue. Note: For your client-side expiration processing, you need to renew the token before your local authenticationToken is about to expire.

Aspnet Core 1.0 Identity User Manager ConfirmEmailAsync returns InvalidToken

When the user clicks the Confirm Email link in the email they receive, the url directs the user to the ConfirmEmailAsync method in the Account Controller.
This method then returns the result of the call to the Email Token Provider.
var result = await _userManager.ConfirmEmailAsync(user, code);
I have captured the generated email token when the user registers and the token that is passed in the code variable above and they are identical.
I have tried Base64 encoding and decoding with no success, although I believe this is done automatically by the asp-net-core-identity-token-providers.
Any ideas ?
Generated tokens through identity are tied to the SecurityStamp on the user. If the stamp is updated for any reason, all previously sent tokens are invalidated. Changing or setting a password would cause this to happen.
This could be an order of operations problem. Do you by chance save the register password after you send the email to validate the email they provided?
For instance, this will fail:
Send email with token
Save the register info like the password
Try to use the token.
Instead, this should work:
Save the register info
Send email with token
Try to use token
That scenario is just an example as I can't be sure that is the way your code is setup. That said, if the tokens are the same, it is likely the securitystamp that is the problem. Keep tabs on it in your database throughout the process and see if something is updating it.

Removing scope for jawbone user

My application has requested moves and sleeps scope for a particular user. Now he wants to remove the sleep scope.
Is there an api to do it? or do I need to re-authorize the user again requesting only one scope?
You will need to re-authorize the user with the updated scope because the user must confirm the permission change.
Send the user down the same authentication flow, and save the new token.

Update token after password change in Phonegap

I am new to token based authentication and doing the following:
Authenticate the user by email and password,
get a token back from backend,
store the token in local storage,
check to see if a token is present. If yes then user is logged in.
What what I want to achieve is that if the user changes his password then the client should prompt for fresh login. How can this be done?
This depends whether you are using Refresh Tokens or not as user Gopinath Shiva describes in his answer to question about somewhat same domain.
If you use Refresh Tokens, then
When the user changes his password, change the refresh token of the user. Hence the remaining session will get logged out soon.
If you don't, then
When the user changes his password, note the change password time in the user db, so when the change password time is greater than the token creation time, then token is not valid. Hence the remaining session will get logged out soon.

How to implement "remember me" using ServiceStack authentication

I am trying to implement a Remember me feature in a ServiceStack-based project. I don't want to use Basic Authentication because it requires storing password in clear text in a browser cookie, so I need to come up with an alternative approach that will be easy to maintain and customized to my existing database.
I understand that ServiceStack's own support for Remember me is based on caching the IAuthSession instance in the server-side cache, which by default is an in-memory data structure that is wiped out when the website restarts (not good). Alternatively, the cache can also be based on Redis or Memcached, which is better (cached data survives website restarts) but adds more moving parts to the picture than I care to add to it.
Instead, I would like to implement the this functionality using my own database:
Table Users:
UserID (auto-incremented identity)
Username
Password
Email
Name
etc...
Table Sessions:
SessionID (auto-incremented identity)
UserID (FK to Users)
StartDateTime
EndDateTime
SessionKey (GUID)
The way I see things working is this:
On login request, AuthService creates an empty instance of my UserAuthSession class (implements IAuthSession) and calls my custom credentials provider's TryAuthenticate method, which authenticates the user against the Users table, populates UserAuthSession with relevant user data and inserts a new record into the Session table.
Then the auth session is cached in the in-memory cache and ServiceStack session cookies (ss-id and ss-pid) are created and sent to the browser.
If the user checks Remember me then additionally my custom credential provider's OnAuthenticate method creates a permanent login cookie that contains the user's username and the auto-generated Sessions.SessionKey. This cookie will help us track the user on subsequent visits even if the auth session is no longer in the cache.
Now, suppose the site has been restarted, the cache is gone, so when our user returns to the site his auth session is nowhere to be found. The current logic in AuthenticateAttribute redirects the user back to the login screen, but instead I want to change the flow so as to to try to identify the user based on my custom login cookie, i.e.:
look up the latest Sessions record for the username extracted from the login cookie
check if its SessionKey matches the key in the login cookie
if they match, then:
read the user's data from the Users table
create my custom auth session instance, fill it with user data and cache it (just like at initial login)
insert a new Sessions record with a new SessionKey value
send back to the browser a new login cookie to be used next time
if the keys don't match then send the user back to the login screen.
Does the above logic make sense?
Has anyone already implemented anything similar using ServiceStack?
If I were to proceed with this approach, what is the best course of action that doesn't involve creating my own custom version of AuthenticateAttribute? I.e. which hooks can I use to build this using the existing ServiceStack code?
This is already built for you! Just use the OrmLiteCacheClient.
In your AppHost.Configure() method, add this:
var dbCacheClient = new OrmLiteCacheClient {
DbFactory = container.Resolve<IDbConnectionFactory>()
};
dbCacheClient.InitSchema();
container.Register<ICacheClient>(dbCacheClient);
I am not sure when this particular feature was added, perhaps it wasn't available when you originally asked. It's available in v4.0.31 at least.