What is the expiry date time of the access token? - .net-core

When we implement the Client Credentials grant - Protecting an API using Client Credentials how long is the access token usable for (e.g. whats is the expiry date) before the client needs to generate a new access token?

When you create a client you can define the lifetime of an access token
var myClient = new Client
{
ClientId = "testClient",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" },
AccessTokenLifetime=3600
};
If you do not supply AccessTokenLifetime then it will default to 3600 which is an hour. This means it will expire one hour after it is created

FYI,
The expiry of a JWT will be represented as Unix epoch.
For instance
{
"exp":1517988642,
...
}
which can be checked in a tool such as https://www.epochconverter.com/

Related

How to make Owin automatically use refresh token when access token expires

I have an Owin client connected to IdentityServer 4, and am wondering how to get owin to request a new access_token using the refresh token. I can successfully get owin to swap the code given for an access_token, id_token and refresh_token with the following configuration:
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookie"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "http://localhost:5000",
ClientId = "mywebsite",
ClientSecret = "secret",
RedirectUri = "https://localhost:5001/",
ResponseType = "code",
RequireHttpsMetadata = false,
SaveTokens = true,
UseTokenLifetime = true,
SignInAsAuthenticationType = "Cookie",
Scope = "openid profile email offline_access",
RedeemCode = true,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
Console.WriteLine(n);
return System.Threading.Tasks.Task.FromResult(0);
},
TokenResponseReceived = n =>
{
Console.WriteLine(n);
return System.Threading.Tasks.Task.FromResult(0);
}
},
});
}
Firstly, where do I save these tokens to? I can access them all the SecurityTokenValidated callback - should they go into the claims? Database? Memory?
Secondly, I have on my IdentityServer client configuration the access_token lifespan set to 60s, identity_token set to 3600s, and refresh to 30 days (please note the access_token is only this short for testing purposes). So how can I configure Owin to recognize that the access_token has expired and that it needs to go back to identityserver with the refresh_token and get a new one. Answers with example code snippets would be appreciated as my knowledge on all this is very small.
Relevant Info:
IS4 v3
.Net Framework v4.6
Client is set in IS to allow offline access
Take a look at this article:
Automatic Token Management for ASP.NET Core and Worker Services 1.0
Otherwise than that there is no logic in the AddOpenIdConnect(..) handler to deal with renewal of refresh tokens. I think its up to your application to refresh them. Refreshing them in code is not that hard if you have saved the refresh token somewhere safe.
See this question How to use 'refresh_token' in IdentityServer 4?

JWT Authorization policy to Ignore expiration (Lifetime)

I am working with JWT authentication in Asp.net core 3.0. The application is already setup to use JWT authentication and it is working fine. What I am looking for is to have an endpoint to be able to accessed even the auth token is expired (but all the other checks must be validated). I read about the policies and authentication schemes and played with those but it didn't help. How this can be made possible? Any help would be appreciated. TIA
That defeats the whole purpose of the system; why would you want that?
You could technically just increase the lifetime of the token, an example with IdentityServer4:
int tokenLifetime = (int)TimeSpan.FromDays(30).TotalSeconds;
services.AddIdentityServer()
.AddInMemoryClients(new[] {
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("some_secret".Sha256())
},
AllowedScopes = { "your-scope" },
AccessTokenLifetime = tokenLifetime
}
});
Another way is to use refresh tokens to renew your access token.

identityserver4 with redux -oidc client requested access token - but client is not configured to receive access tokens via browser

My identityserver4 client looks like this:
new Client {
ClientId = "openIdConnectClient",
ClientName = "Example Implicit Client Application",
//AllowedGrantTypes = GrantTypes.Implicit,
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AccessTokenLifetime = 30,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"role",
"customAPI.write"
},
RedirectUris = new List<string> {"http://localhost:8080/callback"},
PostLogoutRedirectUris = new List<string> {"https://localhost:44330"},
AllowedCorsOrigins = new List<string>
{
"http://127.0.0.1:8080",
"http://localhost:8080",
"*"
},
}
In react application, my userManager class looks like this:
import { createUserManager } from 'redux-oidc';
const userManagerConfig = {
client_id: 'openIdConnectClient',
redirect_uri: `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}/callback`,
//response_type: 'code id_token token',
response_type: 'token id_token',
scope: 'openid profile email role',
authority: 'http://localhost:50604',
silent_redirect_uri: `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}/silent_renew.html`,
automaticSilentRenew: true,
filterProtocolClaims: true,
loadUserInfo: true,
};
const userManager = createUserManager(userManagerConfig);
export default userManager;
The question is: when i try to call my identityserver4 from the redux-oidc example application. I'm getting the following error:
Client requested access token - but client is not configured to receive access tokens via browser
I hope you understood the question. Please someone help me with this. i have provided the link for this example application bellow.
Redux-oidc example app link
Your code contains two different grant types. The different Grant types in Identity server 4 have different requirements. Here is a bit of information to help you understand the different types you are using. It may also help you understand why you were having this problem.
GrantTypes.ClientCredentials
The Client credentials is the simplest grant type and is used for server to server communication - tokens are always requested on behalf of a client, not a user.
With this grant type you send a token request to the token endpoint, and get an access token back that represents the client. The client typically has to authenticate with the token endpoint using its client ID and secret.
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" }
}
GrantTypes.Implicit
The implicit grant type is optimized for browser-based applications. Either for user authentication-only (both server-side and JavaScript applications), or authentication and access token requests (JavaScript applications).
In the implicit flow, all tokens are transmitted via the browser, and advanced features like refresh tokens are thus not allowed. If you want to transmit access tokens via the browser channel, you also need to allow that explicitly on the client configuration:
Client.AllowAccessTokensViaBrowser = true;
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
// where to redirect to after login
RedirectUris = { "http://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
AllowAccessTokensViaBrowser = true
}

Using Firebase REST API with custom token failed with 403 forbidden [duplicate]

I'm migrating to the new database and 3.0 client libs. I'm updating the part which generates a custom auth token (on our server) to do a PATCH to update a resource in the Firebase DB.
These PATCH requests used to be made by our server to Firebase using admin claims based on this: https://www.firebase.com/docs/rest/guide/user-auth.htm
For the new DB, I'm generating the JWT token (using ruby-jwt) like this:
payload = {
aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
claims: custom_claims.merge({ admin: true }),
exp: now_seconds + (60 * 60), # Maximum expiration time is one hour
iat: now_seconds,
iss: service_account_email,
sub: service_account_email,
uid: uid
}
JWT.encode(payload, private_key, "RS256")
A PATCH request with this token to the Firebase DB fails with: Missing claim 'kid' in auth header.
In the new Firebase you need to directly use a Service Account to create administrative access credentials. Here is a Node.js snippet that shows how to make a REST call to the Database:
// key.json is a service account key downloaded from the Firebase Console
var key = require('./key.json');
var google = require('googleapis');
var request = require('request');
var DATABASE_URL = 'https://<databaseName>.firebaseio.com';
var jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database'
]);
jwtClient.authorize(function(err, tokens) {
request({
url: DATABASE_URL + '/.json',
method: 'GET',
headers: {
'Authorization': 'Bearer ' + tokens.access_token
}
}, function(err, resp) {
console.log(resp.body);
});
});
To do the same in Ruby, you might take a look at the googleauth gem for fetching the access token using Service Account credentials.
Here is the equivalent of Michael Bleigh's answer using the ruby googleauth module:
require 'googleauth'
scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/firebase.database']
auth = ::Google::Auth.get_application_default(scopes)
auth_client = auth.dup
auth_client.sub = "service-account-email-here#yourapp.iam.gserviceaccount.com"
token = auth_client.fetch_access_token!
You will also need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your service account JSON file. the value for auth_client.sub comes from client_email in this JSON file.
Of course, as above, this is only valid in a server application you control.
Also, making the request to the firebase REST API is still an exercise for the reader.
references
https://developers.google.com/api-client-library/ruby/auth/service-accounts#authorizingrequests
https://developers.google.com/identity/protocols/application-default-credentials#whentouse

Using Custom Tokens to make REST requests to FB DB as an admin

I'm migrating to the new database and 3.0 client libs. I'm updating the part which generates a custom auth token (on our server) to do a PATCH to update a resource in the Firebase DB.
These PATCH requests used to be made by our server to Firebase using admin claims based on this: https://www.firebase.com/docs/rest/guide/user-auth.htm
For the new DB, I'm generating the JWT token (using ruby-jwt) like this:
payload = {
aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
claims: custom_claims.merge({ admin: true }),
exp: now_seconds + (60 * 60), # Maximum expiration time is one hour
iat: now_seconds,
iss: service_account_email,
sub: service_account_email,
uid: uid
}
JWT.encode(payload, private_key, "RS256")
A PATCH request with this token to the Firebase DB fails with: Missing claim 'kid' in auth header.
In the new Firebase you need to directly use a Service Account to create administrative access credentials. Here is a Node.js snippet that shows how to make a REST call to the Database:
// key.json is a service account key downloaded from the Firebase Console
var key = require('./key.json');
var google = require('googleapis');
var request = require('request');
var DATABASE_URL = 'https://<databaseName>.firebaseio.com';
var jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database'
]);
jwtClient.authorize(function(err, tokens) {
request({
url: DATABASE_URL + '/.json',
method: 'GET',
headers: {
'Authorization': 'Bearer ' + tokens.access_token
}
}, function(err, resp) {
console.log(resp.body);
});
});
To do the same in Ruby, you might take a look at the googleauth gem for fetching the access token using Service Account credentials.
Here is the equivalent of Michael Bleigh's answer using the ruby googleauth module:
require 'googleauth'
scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/firebase.database']
auth = ::Google::Auth.get_application_default(scopes)
auth_client = auth.dup
auth_client.sub = "service-account-email-here#yourapp.iam.gserviceaccount.com"
token = auth_client.fetch_access_token!
You will also need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your service account JSON file. the value for auth_client.sub comes from client_email in this JSON file.
Of course, as above, this is only valid in a server application you control.
Also, making the request to the firebase REST API is still an exercise for the reader.
references
https://developers.google.com/api-client-library/ruby/auth/service-accounts#authorizingrequests
https://developers.google.com/identity/protocols/application-default-credentials#whentouse

Resources