I don't see the way to have both timeouts at the same time in OAuth 2.0.
Regarding only the first timeout, idle timeout, you can set the refresh token timeout to 100 minutes. The access token timeout will be lesser and each time that the access token expires, you will get both new access and refresh tokens. If the user session is idle for more than 100 minutes, when the app try to refresh the token, the oauth server will realise that the refresh token has expired and is not valid. Then the user will need to enter their credentials.
For the second timeout, you can set the access token timeout to 8 hours and don't implement refresh tokens.
Take into account that the token will be sent to the resource server, that could not be the same as the oauth server. The resource server can only check that the ticket into the token is not expired, but has no way to control when the token was granted the first time after the user entered their credentials.
If you control both oauth and resource servers, you could do a workaround implementing the 100 minutes timeout for the refresh token and including in the ticket a property with the time when the user entered the credentials. Please see code below as an example:
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
...
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
...
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"client_id", clientId
},
{
"ownerCredentialsTimestamp", DateTime.UtcNow.ToString()
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
}
...
}
When the resource server obtains the ticket contained in the token, can compare the value in the property with the current time. In the case of the difference is bigger than 8 hours can return a 401 - Unauthorized response, forcing the client app to ask for another access token:
public class AccessTokenProvider : IAuthenticationTokenProvider
{
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
if (context.Ticket.Properties.Dictionary["ownerCredentialsTimestamp"] != null)
{
var ownerCredentialsTimestamp = Convert.ToDateTime(context.Ticket.Properties.Dictionary["ownerCredentialsTimestamp"]).ToUniversalTime();
if (/* difference is bigger than 8 hours */)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
}
}
}
At this point, the client app will try to obtain a new access token with a "refresh_token" request. The oauth server has to check again the time of the last entered credentials related with the current refresh token, there could be a column in database table where storing refresh tokens (if this is your case).
You could check it in RefreshTokenProvider.ReceiveAsync() method:
public class RefreshTokenProvider : IAuthenticationTokenProvider
{
...
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
...
/* Check the received refresh token, including the last time that the credentials were entered for this user */
...
}
...
}
Or in AuthorizationServerProvicer.GrantRefreshToken() method:
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
...
public override async Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
...
/* Check the last time that the credentials were entered for this user */
...
}
...
}
This is a very particular solution that has nothing to do with OAuth 2.0 protocol.
I hope it helps you.