Why OAuth2 Tokens Miss expires_in and How Spring Security Handles It

The article examines why the demo environment of pig4cloud returns an OAuth2 access token without the expires_in field, contrasts it with a local deployment, analyzes the Spring Security OAuth2 token generation code, and explains that according to the OAuth2 specification the expires_in parameter should be returned even for permanently valid tokens.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Why OAuth2 Tokens Miss expires_in and How Spring Security Handles It

Problem Background

Someone asked why the demo environment of pig4cloud returns a login response without the expires_in field, while a locally deployed instance includes it.

{
    "access_token":"16d35799-9cbb-4c23-966d-ab606029a623",
    "token_type":"bearer",
    "refresh_token":"495dbde5-1bbb-43c9-b06b-ecac50aa5d53",
    "expires_in":41000,
    "scope":"server"
}

In the local deployment the response looks like:

{
    "access_token":"c262afbe-441e-4023-afb4-f88c8a0a7d51",
    "token_type":"bearer",
    "refresh_token":"ea642d50-5cf5-48ad-9ef9-cb57c9dde00a",
    "scope":"server"
}

The missing expires_in parameter means the client cannot know when to refresh the token.

Source Code Analysis

In Spring Security OAuth2 the token creation method adds the expires_in field only when the configured token validity (validSeconds) is greater than zero.

OAuth2AccessToken createAccessToken() {
  DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
  int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
  if (validitySeconds > 0) {
    token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
  }
  token.setRefreshToken(refreshToken);
  token.setScope(authentication.getOAuth2Request().getScope());

  return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
}

When the token store saves a token with an expiration of zero or negative, the expiration is null, meaning the token is considered permanently valid, and the expires_in field is omitted in the response.

if (token.getExpiration() != null) {
  int seconds = token.getExpiresIn();
  conn.expire(accessKey, seconds);
  conn.expire(authKey, seconds);
  conn.expire(authToAccessKey, seconds);
  conn.expire(clientId, seconds);
  conn.expire(approvalKey, seconds);
}

Should a permanently valid token return expires_in?

According to the OAuth2 specification, the expires_in field is recommended to be returned regardless of whether the token has a limited lifetime.

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
  "token_type":"bearer",
  "expires_in":3600,
  "refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
  "scope":"create"
}

access_token (required): the token issued by the authorization server.

token_type (required): typically the string "bearer".

expires_in (recommended): lifetime of the access token in seconds.

refresh_token (optional): token used to obtain a new access token after expiration.

scope (optional): the granted scope.

Therefore, Spring Security OAuth2’s omission of expires_in for permanently valid tokens does not conform to the specification.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

OAuth2spring-securityaccess_tokenexpires_intoken expiration
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.