Use access token and refresh token returned by Identity API endpoints
In the previous part of this series we wired token based authentication and Identity API endpoints into our Employees Web API. Now it's time to test and confirm the working of our API.
At this stage the Swagger UI is listing all the Identity API endpoints such as /register and /login but there is no way to specify the authentication token while calling the Employees Web API. To fix this, we need to add some Swagger configuration. If you aren't familiar with this configuration, I suggest you read this article first.
Open Program.cs from EmployeeWebApi project and add this configuration just before AddSwaggerGen() call :
var securityScheme = new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
In = ParameterLocation.Header
};
var securityReq = new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
};
Basically, we created OpenApiSecurityScheme and OpenApiSecurityRequirement objects to support bearer token authentication scheme in the Authorization HTTP header. I won't go in much details of this code here.
Then substitute the AddSwaggerGen() call with this modified call :
builder.Services.AddSwaggerGen(o =>
{
o.AddSecurityDefinition("Bearer", securityScheme);
o.AddSecurityRequirement(securityReq);
});
As you can see, we passed the OpenApiSecurityScheme and OpenApiSecurityRequirement objects in the Swagger configuration.
Now, when you run the Employee Web API project, the Swagger UI will display Authorize option with a lock icon in front of all the endpoints and also globally at the top.
You can use the Authorize dialog to specify the bearer token to be used for the authentication. However, first things first.
We will first create a new user in the system. By default, ASP.NET Core Identity uses email as a login name. So, we need a valid email address and a password that meets the validation criteria of ASP.NET Core Identity (minimum length, special characters, no duplicates etc.).
Run the Web API project again and go to /register endpoint. Click on the Try it out button and invoke the API by specifying the user details as shown below:
{
"email": "user1@example.com",
"password": "*****"
}
Make sure to replace the password as per your choice. Execute the API and see the response status code.
Confirm the user creation in the AspNetUsers table from the SQL Server database. The following figure shows this table with a few users added.
Now that we have created a user, we can go ahead and generate a security token for our use.
Invoke the /login endpoint and supply the user credentials as shown below:
Once you execute the /login successfully, you will get three important pieces in the response -- accessToken, refreshToken, and expiresIn.
The accessToken is the authentication token we need to invoke the protected Employees Web API. This token, by default, expires in 3600 seconds. And we can use refreshToken to get another accessToken by invoking /refresh endpoint without needing user credentials again. It should be noted that the accessToken is not a JWT (JSON Web Token).
Before we use the accessToken just obtained from /login, let's confirm that /api/employees throws an exception if valid token is not provided.
Invoke the /api/employees endpoint without supplying any accessToken and you should get this error status code:
As you can see, the response status code is 401 - Unauthorized.
Now let's try again by supplying the accessToken. Click on the lock icon in front of the /api/employees entry. This will open the following dialog:
In the value textbox enter the word Bearer followed by a white space and then the accessToken obtained from /login call.
Close this dialog and invoke the /api/employees endpoint again. This time it will return the Employee data indicating a successful run.
The accessToken returned by /login has expiresIn setting of 3600 seconds. This is too long for our quick testing. We will lower this timeout value and confirm that the accessToken really expires in the specified time.
Open Program.cs and add the following just below the AddIdentityApiEndpoints() and AddEntityFrameworkStores() calls.
builder.Services.ConfigureAll
<BearerTokenOptions>(option => {
option.BearerTokenExpiration =
TimeSpan.FromMinutes(1);
});
As you can see, we set the BearerTokenExpiration property to 60 seconds. This will expire the accessToken in 60 seconds and the accessToken will be considered stale and invalid.
Run the Web API project again and invoke the /api/employees by generating an accessToken as discussed earlier. Once you successfully invoke /api/employees, wait for some time (more than 60 seconds) and then try to invoke the API again. This time you will get an error because the access token is now stale and invalid.
One way to fix this situation is to again invoke /login and get another accessToken. However, this will require us to send user credentials again to the /login endpoint. The refreshToken comes handy in such cases. Instead of passing user credentials again, you can pass the refreshToken to /refresh endpoint and get another accessToken (and another refreshToken).
Let's do that in our example.
Navigate to the /login endpoint again and copy the refreshToken. You may consider saving it in a text editor for our testing purpose.
Now, go to the /refresh endpoint and invoke it by specifying the refreshToken.
You will get another accessToken and refreshToken. Invoke the /api/employees endpoint again with this new accessToken. This time you will get success because it's a new accessToken valid for another 60 seconds. You can use the new refreshToken to get a fresh accessToken as discussed.
So, we used /register, /login, and /refresh Identity API endpoints to call our Employee Web API /api/employees.
That's it for now! Keep coding!!