Reputation: 24442
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 OAuth2ClientContext
s so they could store individual accessTokens.
Could someone explain if this makes sense or what I am not understanding?
Upvotes: 1
Views: 3320
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