codependent
codependent

Reputation: 24442

Spring Security Oauth2 - InsufficientAuthenticationException: Authentication is required to obtain an access token (anonymous not allowed)

I am trying to understand why anonymous users in the client can't get an access token.

I found this post on the Spring Blog regarding this topic, where Dave Syer answers this:

Remember this is an issue to do with the client app, not the auth server, so try and see it from the point of view of the cllient. At step 1. there is a user trying to access a protected resource. If you can't idenitify that user then all your users end up with the same access token (the one that the first user obtains using his credentials at the auth server). This is definitely a bad idea.

However I don't see why anonymous users would share the same token:

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    if (auth instanceof AnonymousAuthenticationToken) {
        if (!resource.isClientOnly()) {
            throw new InsufficientAuthenticationException(
                    "Authentication is required to obtain an access token (anonymous not allowed)");
        }
    }

Although they are not fully authenticated, they have a JSESSIONID bound to every individual anonymous user.

The OAuth2ClientContext, which would contain the accessToken, is a session scoped Spring bean. Since anonymous users have a HttpSession they have independent OAuth2ClientContexts so they could store individual accessTokens.

Could someone explain if this makes sense or what I am not understanding?

Upvotes: 1

Views: 3320

Answers (1)

rocky
rocky

Reputation: 5004

This is not really bound to session I believe. Dave probably meant that you can have just one anonymous user in spring context. It was always a mystery for me why this anonymous user term exists, but its different story.

Look at code of method getAccessToken in JdbcClientTokenServices class

public OAuth2AccessToken getAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication) {

    OAuth2AccessToken accessToken = null;

    try {
        accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {
            public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
                return SerializationUtils.deserialize(rs.getBytes(2));
            }
        }, keyGenerator.extractKey(resource, authentication));
    }
    catch (EmptyResultDataAccessException e) {
        if (LOG.isInfoEnabled()) {
            LOG.debug("Failed to find access token for authentication " + authentication);
        }
    }

    return accessToken;
}

It uses serialized authentication in database. So even in different session its going to use same anonymous user to load token effectively loading the very same token.

In authorization_code oauth2 flow you need code to fetch token (so 1st step is to ask for code, which will be given only after authorizing user -user may be redirected to lets say facebook during this step). 2nd step is fetching token by giving code. code has bounded authorization in db, so spring knows who is an owner of new token:

\d+ oauth_code;
                                                     Table "mydb.oauth_code"
     Column     |          Type          |                        Modifiers                        | Storage  | Stats target | Description
----------------+------------------------+---------------------------------    ------------------------+----------+--------------+-------------
 id             | integer                | not null default     nextval('oauth_code_id_seq'::regclass) | plain    |              |
 authentication | bytea                  |                                                         | extended |              |
 code           | character varying(255) |                                                         | extended |              |

So, to sum up, having OAuth2ClientContext with scope session or request will not help you if you are going to fill it with the same token.

Upvotes: 1

Related Questions