Test Refresh Tokens in IdentityServer4 - identityserver4

We are using IdentityServer4 to protect our APIs with EntityFrameworkCore to store configuration and operational data.
Here is our client data:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" },
AllowOfflineAccess=true
},
new Client
{
ClientId = "client2",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "sup_api" },
AllowOfflineAccess=true
}
};
}
We posted request to connect/token endpoint,with following data in "x-www-form-urlencoded" format
client_id:client2
client_secret:secret
grant_type:client_credentials
scope:sup_api
and we have got the following response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjM2ZWE2MGZlNGY2NDZkYjIxZjI0Y2ExNjEzZTBmMTgyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTk4OTM1MTYsImV4cCI6MTUxOTg5MzU2NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJzdXBfYXBpIl0sImNsaWVudF9pZCI6ImNsaWVudDIiLCJzY29wZSI6WyJzdXBfYXBpIl19.cOznF6F6AL8onLZvvJaSX137P19k6doNa2BoJJTs6WY1LL47UOWoPhR7xIffQVSKyxGp4r-Z02kZrABjjyXzcdTaCR4538Pexep2sjlPobmKI0rfjR2apBSaMBVFXqDW-3VLTnMPyqicIBYjll5iS8YFGpUh0jZwq4rzNvYR4OooHssijQtkhpWxGzuokjKj8ZK1conySqEqorlaFJevY2x4jNlP3v0wpJ_6p77H4Lh12XENw4laGlrejtOkilnRaT7V8CclRGNsgPc81NLJhQZEp89cl37iQ1vLH74hCSs4MllO_eAZ_3Rmdan6QWUM1_zbcCEjGbXJM0QQ2qCpHw",
"expires_in": 3600,
"token_type": "Bearer"
}
But now, how we can test refresh tokens?

One way to do this is check if user still has access after the access token expiration time.
E.g.
At a high level this is what it would look like
Set access token lifetime to 1 minute
Run access test against API at 6 minute mark (there is a inbuilt delay when it actually expires the token)
You should assert that 401 will return, if it does then pass
Activate offline token
Run access test after 6 minute mark
Assert that you get non 401 response, if so then pass
It more testing of

Related

LogoutRequest has no PostLogoutRedirectUri in it when using React.js app with ... library

I have an Identity Server 4 instance running at https://localhost:5443/ and a client React.js application running at http://localhost:3000/ and making a reference to the oidc-client library in order to establish the communication. I've been following more or less this article.
The way I've configured the client (in-memory) on the Identity Server is as follows:
new Client
{
ClientId = "react-js-implicit-flow",
ClientName = "Some App name",
ClientUri = "http://localhost:3000",
AllowedGrantTypes = GrantTypes.Implicit,
RequireClientSecret = false,
RedirectUris = { "http://localhost:3000/signin-oidc", },
PostLogoutRedirectUris = { "http://localhost:3000/signout-oidc" },
AllowedCorsOrigins = { "http://localhost:3000" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"weatherapi.read"
},
AllowAccessTokensViaBrowser = true
}
and the way it looks like on the Ract.js app is like this:
In general, everything goes well. I can login and logout from the Identity Server but the issue is that here:
I get no value (it is null) and this stops the Identity server from redirecting me back to the client application right after logout. If I hard code it (http://localhost:3000/signout-oidc) it works. But for some reason it is just not available.
During the logout this is what the Identity Server logs show:
So, no error, no nothing but I still can not navigate back to the client app after logout.
You do not provide an idTokenHint (id token) with your logout request like the following:
const mgr = new Oidc.UserManager(settings);
const signoutUrl = await mgr.createSignoutRequest({id_token_hint: user.id_token});
window.location.href = signOutUrl.url;
//or
await mgr.signoutRedirect({id_token_hint: user.id_token});
//or just
await mgr.signoutRedirect();
//it will try to attach id_token internally
Lack of the token is the reason for Identityserver to skip the post_logout_redirect_url parameter.
Identityserver has to validate the parameter against the client's configuration, but without the token it can't.
What solved the issue for (me thanks to answer by #d_f) was to change something on the client side and more specifically: src/services/userService/signoutRedirect.

How to request additional claims for access token in identity server 4 / auth code flow?

How do you request additional claims for the access token jwt in identity server 4 / auth code flow? My custom profile service always shows RequestedClaimTypes of 0 during my auth code flow signin so the resulting access token jwt has my subject claim but no firstname, lastname, or email claim.
Here are my requested scopes from the client:
"TestApi openid profile email"
Here is my client definition on identity server:
new Client {
ClientId = "authorizationCodeClient2",
ClientName = "Authorization Code Test",
ClientSecrets = {
new Secret("secret".Sha256())
},
Enabled = true,
AllowedGrantTypes = GrantTypes.Code,
RequireConsent = true,
AllowRememberConsent = false,
RedirectUris =
new List<string> {
"http://localhost:5436/account/oAuth2"
},
AllowedScopes = { "TestApi", "openid", "profile", "email" },
AccessTokenType = AccessTokenType.Jwt
}
Using https://github.com/bayardw/IdentityServer4.Authorization.Code for the test client.
I discovered that identity server will let you optionally stamp the id token with the user profile claims (instead of having to call the userinfo endpoint). You basically set a Boolean property for that particular client:
AlwaysIncludeUserClaimsInIdToken = true;
Note, you will want to request the following scopes on your auth request : (openid profile email)

IdentitySever4 user claims and ASP.NET User.Identity

I've written a small IdentityServer demo server, following the examples in the documentation. I have the following TestUser:
new TestUser
{
SubjectId = "1",
Username = "Username",
Password = "password",
Claims = new List<Claim>()
{
new Claim(System.Security.Claims.ClaimTypes.Name, "Username"),
new Claim(System.Security.Claims.ClaimTypes.Email, "username#domain.com")
}
}
I get an access token using ResourceOwnerPassword flow. And I am authorized to access my API.
The problem is that when in my protected API I'm trying to get the user identity, the name property is returned as null, and I don't see the email claim. No matter what I do I always see the same 12 claims. The sub claim is the only one passed with the information I put in the Client object.
How can I populate the HttpContext.User.Identity.Name property and send additional claims/data about the user?
The reason probably is that you are not requesting the proper resources/scopes for your client.
You need to define an API resource with the claims you need in the access token.
e.g in Resources.cs you can add the claims to be included in all api2 scopes
new ApiResource
{
Name = "api2",
ApiSecrets =
{
new Secret("secret".Sha256())
},
UserClaims =
{
JwtClaimTypes.Name,
JwtClaimTypes.Email
},
Scopes =
{
new Scope()
{
Name = "api2.full_access",
DisplayName = "Full access to API 2",
},
new Scope
{
Name = "api2.read_only",
DisplayName = "Read only access to API 2"
}
}
}
Then you allow your resource owner client the access to those API resources.
e.g in client.cs
new Client
{
ClientId = "roclient",
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
AllowOfflineAccess = true,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
"custom.profile",
"api1", "api2.read_only"
}
},
You can then request the scope in your roclient
client.RequestResourceOwnerPasswordAsync("bob", "bob", "api2.read_only", optional).Result
Post the access token to the API and you will get the claims you added to your API resource.
In the call to UseOpenIdConnectAuthentication, or wherever you're trying to use the token, make sure you set the TokenValidationParameters for the Name property to ClaimTypes.Name.
By default, the Name claim type is set to name (JwtClaimType.Name).

How do you request an Identity Token (id_token) in IdentityServerr4

I'm new to Identity Server and am confused on the topic of Identity & Access tokens. I understand access tokens are meant to secure resources (i.e. web api) and that identity tokens are used to authenticate. However, whenever I call /connect/token I always receive an "access_token". Within the request I've asked for a client which has various scopes and claims.
new Client
{
ClientId = "Tetris",
ClientName = "Tetris Web Api",
AccessTokenLifetime = 60*60*24,
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
RequireClientSecret = false,
AllowedScopes = {"openid", "TetrisApi", "TetrisIdentity"}
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new[]
{
new ApiResource("TetrisApi", "Tetris Web API", new[] { JwtClaimTypes.Name, JwtClaimTypes.Role, "module" })
};
}
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource
{
Name = "TetrisIdentity",
UserClaims =
new[]
{
JwtClaimTypes.Name,
JwtClaimTypes.Role,
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName,
JwtClaimTypes.Email,
"module",
"module.permissions"
}
}
};
}
Below is a copy of postman:
Any thoughts? I didn't see an example in the Quickstarts that employs Identity Tokens.
Thanks!
The password grant type does not support identity tokens. See RFC6749.
The best you can do here is to use the access token to get claims for the user using the userinfo endpoint.
The recommendation is to use an interactive flow like implicit or hybrid for end-user authentication.
#leastprivilege 's answer is correct but instead of calling the userinfo endpoint, you also have the option of including the UserClaims you desire in your ApiResource definition.
At the moment you request new[] { JwtClaimTypes.Name, JwtClaimTypes.Role, "module" }, but if you changed that to include all the claims you (currently) define as part of the IdentityResources then those claims will also be available in the access_token.

Set Token Validation Period in Identity Server 4

What is the mechanism for setting a token validation period in Identity Server 4? Can the validation period vary for different tokens?
The Identity Server 4 documentation at http://docs.identityserver.io/en/dev/ shows a AuthorizationEndpoint with a property max_age, which is what I think I want, but the documentation does not really show it it inter-operates with the quickstart code for IdentityServerWithAspNetIdentity.
I have modified the Client object in Config.cs of the IdentityServerWithAspNetIdentity
// OpenID Connect hybrid flow and client credentials client (MVC)
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
ClientSecrets =
{
new Secret("LynxJournal".Sha256())
},
//RedirectUris = { "http://localhost:5002/signin-oidc" },
//PostLogoutRedirectUris = { "http://localhost:5002" },
RedirectUris = { serverConfig["MvcClientUrl"] + "/signin-oidc" },
PostLogoutRedirectUris = { serverConfig["MvcClientUrl"] },
IdentityTokenLifetime = 3600,
AccessTokenLifetime = 3600,
AuthorizationCodeLifetime = 3600,
AllowedScopes =
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
StandardScopes.OfflineAccess.Name,
"api1"
}
}
This extends the life of the token to one hour where before the defaults seemed to give about 15-20 minutes. I added values for IdentityTokenLifetime, AccessTokenLifetime and AuthorizationCodeLifetime
Token lifetimes are set per client application. This includes both identity and access tokens. See client application entity.
If you are talking about session length this is set by each application upon successful authentication using IdentityServer.

Resources