What is the difference between Bearer Token and Refresh Token? - servicestack

In ServiceStack, I am using JwtAuthProvider, where I got Bearer Token and Refresh token so how do I verify the token and authorize the web api service?
Code:
var client = new JsvServiceClient(ListeningOn) { UserName = "tuser", Password = "password" };
client.Send<AssignRolesResponse>(new AssignRoles
{
UserName = "tuser",
Roles = new ArrayOfString("TestRole"),
Permissions = new ArrayOfString("GetStatus")
});
var jwtToken = client.Send(new Authenticate()).BearerToken;
Here, What is the use of 'jwtToken' value? user is already authorized and authenticated so I don't get the idea why the token needed here?
Could anyone suggest me how do I take advantage of that token?
JWT Config:
this.Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[]
{
new JwtAuthProvider(AppSettings) {
RequireSecureConnection = false,
AuthKey = AesUtils.CreateKey(),
//CreatePayloadFilter = (payload,session) =>
// payload["CreatedAt"] = session.CreatedAt.ToUnixTime().ToString(),
CreatePayloadFilter = (jwtPayload, session) =>
jwtPayload["exp"] = DateTime.UtcNow.AddSeconds(-1).ToUnixTime().ToString()
},
new CredentialsAuthProvider(AppSettings),
new BasicAuthProvider()
}));

Please see this article on the purpose of JWT Refresh Tokens.
In summary, the BearerToken the actual JWT and what used to authenticate via JWT. It's contains a stateless snapshot of the Users Session and is typically a short-lived token, which after it expires needs to contact the Auth Server to fetch a new JWT Token.
The RefreshToken is a longer-lived token which can be used to request new JWT Tokens transparently (i.e without forcing the User to manually re-authenticate) and will be populated with the latest snapshot of the Users Session.
The shorter the lifetime of JWT BearerTokens the less stale the stateless Session information that's stored in the JWT but the more often the RefreshToken will need to be used to fetch an updated BearerToken. Only after a new BearerToken is requested will session information like the Roles and Permissions has or whether they're locked out.
The lifetime of each Token is configurable with the ExpireTokensIn and ExpireRefreshTokensIn JwtAuthProvider properties.
ServiceStack Clients built-in support for JWT and Refresh Tokens
ServiceStack's Service Clients automatically take care of transparently fetching new JWT Tokens using RefreshTokens. You would typically populate both the BearerToken and RefreshToken when initializing your Service Client, e.g:
var authResponse = authClient.Send(new Authenticate());
var client = new JsonServiceClient(baseUrl) {
BearerToken = authResponse.BearerToken,
RefreshToken = authResponse.RefreshToken,
};
The BearerToken is needed to make the request although since the Service Client automatically fetches new JWT Tokens with the configured RefreshToken you only need to populate the RefreshToken:
var client = new JsonServiceClient(baseUrl) {
RefreshToken = authResponse.RefreshToken,
};
As ServiceStack will automatically fetch a new JWT Token on first use, but you can save a round-trip by populating both.

Related

Token management for ClientSecretCredential usage in MSGraph API

I need to send mails from a background application(worker service/azure function) using MSGraph API with Application permission. This is how I have initialized the GraphServiceClient to send emails.
var credentials = new ClientSecretCredential(
"TenantID",
"ClientId",
"ClientSecret",
new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud });
GraphServiceClient graphServiceClient = new GraphServiceClient(credentials);
var subject = $"Subject from demo code";
var body = $"Body from demo code";
// Define a simple e-mail message.
var email = new Microsoft.Graph.Message
{
Subject = subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = body
},
ToRecipients = new List<Recipient>()
{
new Recipient { EmailAddress = new EmailAddress { Address = "EmailId" }}
}
};
// Send mail as the given user.
graphServiceClient
.Users["UserID"]
.SendMail(email, true)
.Request()
.PostAsync().Wait();
How long the graphServiceClient will have a valid token and how to regenerate a token when the token is expired.
What are the best practices for this usage
The default lifetime of an access token is variable. When issued, an access token's default lifetime is assigned a random value ranging between 60-90 minutes (75 minutes on average). Please refer this DOC for more information.
The refresh tokens can be used to acquire access tokens if they expire, Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time.
For getting the access tokens with client secret please refer this method of getting the access tokens.
Hope this will help.
As of May 2022, there is no option to generate a refresh token while using client_credentials options.
For client_credentials option
It's possible to generate a refresh token while using on behalf of user
For on behalf of a user

How to query MS Graph API in User Context?

I'm trying to change a user's password using MS Graph API. I was checking earlier questions like this and this where the answer were always similar: register an AAD application, because changing the password requires Delegated
UserAuthenticationMethod.ReadWrite.All permissions, and you cannot set that in a B2C application as a B2C app supports only offline_access and openid for Delegated.
So the answers were always suggesting creating an AAD app, and using this app I could query the Graph API on behalf of the user. The question is, how to achieve this? If I check the documentation from Microsoft: Get access on behalf of a user, it is saying that first you need to get authorization, only then you can proceed to get your access token.
But as part of the authorization process, there is a user consent screen. If I'm calling my ASP.NET Core Web API endpoint to change my password on behalf of my user, how will it work on the server? The client won't be able to consent, if I'm doing these calls on the server, right?
Also, I'm using Microsoft.Graph and Microsoft.Graph.Auth Nuget packages and it's not clear how to perform these calls on behalf of the user. I was trying to do this:
var client = new GraphServiceClient(new SimpleAuthProvider(authToken));
await client.Users[myUserId]
.ChangePassword(currentPassword, newPassword)
.Request()
.PostAsync();
Where SimpleAuthProvider is just a dummy IAuthProvider implementation.
Any ideas how to make this work?
OK, got it:
static void ChangePasswordOfAUser()
{
var myAzureId = "65e328e8-5017-4966-93f0-b651d5261e2c"; // id of B2C user
var currentPassword = "my_old_pwd";
var newPassword = "newPassword!";
using (var client = new HttpClient())
{
var passwordTokenRequest = new PasswordTokenRequest
{
Address = $"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
ClientId = clientId, // client ID of AAD app - not the B2C app!
ClientSecret = clientSecret,
UserName = $"{myAzureId}#contoso.onmicrosoft.com",
Password = currentPassword,
Scope = "https://graph.microsoft.com/.default" // you need to have delegate access
};
var response = client.RequestPasswordTokenAsync(passwordTokenRequest).Result;
var userAccessToken = response.AccessToken;
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {userAccessToken}");
var json = System.Text.Json.JsonSerializer.Serialize(new
{
currentPassword = currentPassword,
newPassword = newPassword
});
var changePasswordResponse = client.PostAsync(
$"https://graph.microsoft.com/v1.0/users/{myAzureId}/changePassword",
new StringContent(json, Encoding.UTF8, "application/json"))
.Result;
changePasswordResponse.EnsureSuccessStatusCode();
}
}

Azure ADAL - How to get refresh token / how to refresh access token for nodejs backend server to server connection?

I'm using adal-node module for my Node JS backend to write file to Azure Storage. The authentication works fine, but the access token I got only valid for 1 hour. And so far I couldn't find anyway to refresh my access token. Can someone advise?
I've tried to get refresh token. But the auth function I'm using below don't send refresh token back. I've also try to just create a new token after a while using the same auth function, but it turns out the token is always the same.
Here's the code I use to get the access token.
var AuthenticationContext = require('adal-node').AuthenticationContext;
var authorityHostUrl = 'https://login.windows.net';
var tenant = 'myTenant.onmicrosoft.com'; // AAD Tenant name.
var authorityUrl = authorityHostUrl + '/' + tenant;
var applicationId = 'yourApplicationIdHere'; // Application Id of app registered under AAD.
var clientSecret = 'yourAADIssuedClientSecretHere'; // Secret generated for app. Read this environment variable.
var resource = '00000002-0000-0000-c000-000000000000'; // URI that identifies the resource for which the token is valid.
var context = new AuthenticationContext(authorityUrl);
context.acquireTokenWithClientCredentials(resource, applicationId, clientSecret, function(err, tokenResponse) {
if (err) {
console.log('well that didn\'t work: ' + err.stack);
} else {
console.log(tokenResponse);
}
});
Need some way to refresh my access token so that my long running job wouldn't stop.
Just get a new access token.
In the Client Credentials flow, a refresh token is not returned. (See Section 4.4.3 of the OAuth 2.0 spec.)

Extend the Expiry Time and Date in Firebase OAuth2 access JWT Token

I want To set the maximum Expiry Date and Time for Firebase OAuth2 JWT Access Token - https://firebase.google.com/docs/database/rest/auth
I tried some methods Not working. Here is the Google's Code to generate an Access Token for Firebase Real-time Database
Google APIs Node.js Client
var {google} = require("googleapis");
// Load the service account key JSON file.
var serviceAccount = require("./myfileauth.json");
// Define the required scopes.
var scopes = [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/firebase.database"
];
// Authenticate a JWT client with the service account.
var jwtClient = new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
scopes
);
// Use the JWT client to generate an access token.
jwtClient.authorize(function(error, tokens) {
if (error) {
console.log("Error making request to generate access token:", error);
} else if (tokens.access_token === null) {
console.log("Provided service account does not have permission to generate access tokens");
} else {
var accessToken = tokens.access_token;
console.log(accessToken);
}
});
but it's working for a Short time only I want to Increase its Expiry date and time...
If you want to have longer-lived session tokens, I recommend looking into session cookies. These can be created from the Firebase Admin SDK, and list this as one advantage:
Ability to create session cookies with custom expiration times ranging from 5 minutes to 2 weeks.
It works by taking the ID token (from the client) that is part of the normal Firebase authentication flow, and exchanging that for a session cookie (on the server) with:
// Set session expiration to 5 days.
const expiresIn = 60 * 60 * 24 * 5 * 1000;
// Create the session cookie. This will also verify the ID token in the process.
// The session cookie will have the same claims as the ID token.
// To only allow session cookie setting on recent sign-in, auth_time in ID token
// can be checked to ensure user was recently signed in before creating a session cookie.
admin.auth().createSessionCookie(idToken, {expiresIn}).then((sessionCookie) => { ...

how to refresh token servicestack typescript

On servicestack it says that for regular client it should be like that but for typescript it should be somehow different. Anyone knows how to do it?
var client = new JsonServiceClient(baseUrl);
client.OnAuthenticationRequired = () => {
client.BearerToken = authClient.Send(new Authenticate()).BearerToken;
};
Support for onAuthenticationRequired and refreshToken was added to the TypeScript servicestack-client in v0.0.32 where they can be used to transparently handle 401 Unauthorized Responses and re-authenticate the JsonServiceClient from within the callback before it automatically retries the original failed request:
Transparently handle 401 Unauthorized Responses
If the server returns a 401 Unauthorized Response either because the client was Unauthenticated or the configured Bearer Token or API Key used had expired (or was invalidated), you can use onAuthenticationRequired callback to re-configure the client before automatically retrying the original request, e.g:
client.onAuthenticationRequired = async () => {
const authClient = new JsonServiceClient(authBaseUrl);
authClient.userName = userName;
authClient.password = password;
const response = await authClient.get(new Authenticate());
client.bearerToken = response.bearerToken;
};
//Automatically retries requests returning 401 Responses with new bearerToken
var response = await client.get(new Secured());
Automatically refresh JWT Tokens
With the Refresh Token support in JWT you can use the refreshToken property to instruct the Service Client to automatically fetch new JWT Tokens behind-the-scenes before automatically retrying failed requests due to invalid or expired JWTs, e.g:
//Authenticate to get a new Refresh Token
const authClient = new JsonServiceClient(authBaseUrl);
authClient.userName = userName;
authClient.password = password;
const authResponse = await authClient.get(new Authenticate());
//Configure client with RefreshToken
client.refreshToken = authResponse.RefreshToken;
//Clients will automatically retrieve new JWT Tokens as needed
var response = await client.get(new Secured());
Send Refresh Tokens to an alternate server
Use the refreshTokenUri property when refresh tokens need to be sent to a different ServiceStack Server that issues new JWT Tokens, e.g:
client.refreshToken = refreshToken;
client.refreshTokenUri = authBaseUrl + "/access-token";

Resources