Hi Shiro users,
I have been reading through an old thread from August 2012, titled REST
based token auth approach
<http://mail-archives.apache.org/mod_mbox/shiro-user/201208.mbox/%3CE117088B12CD4297BA0FBF75E23F1D4B%40hifiit.com%3E>
.
In that thread, Les Hazlewood proposes
<http://mail-archives.apache.org/mod_mbox/shiro-user/201208.mbox/%3CCAAtvD4VrOMdudAK4LwqDziN6A5Z%2BUwu%3D0GRrooC8QvXpd4rV1A%40mail.gmail.com%3E>
the following class structure to implement a Bearer-Token authentication
mechanism using Shiro:
public class BearerAuthenticationToken implements AuthenticationToken {
public BearerAuthenticationToken(String token) {/*...*/}
// ...
}
public class BearerTokenRealm extends AuthenticatingRealm {
public BearerTokenRealm() {
setAuthenticationTokenClass(BearerAuthenticationToken.class);
}
public AuthenticationInfo
doGetAuthenticationInfo(AuthenticationToken token) throws
AuthenticationException {
BearerAuthenticationToken bearerToken = (BearerAuthenticationToken)token;
//assert the bearerToken, and if valid, look up the account data and return
//an AuthenticationInfo instance representing that account.
}
}
public class BearerTokenAuthenticatingFilter extends AuthenticatingFilter {
@Override
public AuthenticationToken createToken(/*...*/) {/*...*/}
}
When looking at those suggestions, I realized that I don't fully understand
this part of the Shiro's design. Here are a few questions that I have after
studying the docs, source code, and the Shiro user mailing list archives. I
hope that you an help answer them:
1. When implementing an AuthenticationToken, I have to implement both
`Object getPrincipal()` and `Object getCredentials()` member functions. In
case of a bearer token, having both makes no sense, and I'm not sure which
of the following options I should choose (I couldn't figure out what to do
based on the docs):
- Make `getPrincipal()` always return `null`, and make
`getCredentials()` return the bearer token that was passed into the
constructor, that is called in
`BearerTokenAuthenticatingFilter.createToken(...)`.
This seems wrong, because now I'm returning the bearer token in the
wrong type (Object, instead of String).
- Make both `getPrincipal()` and `getCredentials()` always return
null, and add a new method `String getBearerToken()` that returns the
bearer token that was passed into the constructor.
This fixes the problem I have with the other alternative.
- In both scenarios, some/all of the methods that AuthenticationToken
requires will return null, and from the docs and browsing the
source code,
I could not tell if that will be a problem down the line.
Where are AuthenticationToken instances used?
According to the only callsite for any of these members that I could
find so far (i.e. BearerTokenRealm), leaving `getPrincipal()` and
`getCredentials()` to return null in favor of `getBearerToken()` would
work. Are there any ramifications to doing this?
2. In `BearerTokenRealm.doGetAuthenticationInfo()` I have to turn the
`BearerAuthenticationToken` into an `AuthenticationInfo` object, if the
underlying bearer token is valid. I.e. this is where the authentication
happens, correct? (Failed authentication throws an exception or returns
null.)
I looked through the source code to see which pre-existing
implementation of `AuthenticationInfo` exist, but I didn't quite find one
that suited me - perhaps because I don't understand them well enough.
- What puzzles me is that an AuthenticationInfo has to implement
`PrincipalCollection getPrincipals()`. At this point in my application, I
would have to use the bearer token and use it to compile a list of all
other principals for the Subject that this bearer token belongs to. Why?
Would it be enough if I only look up a single principal, such as a
3rd-party app ID that the bearer token was generated for?
- Even in case I'd be dealing with a UsernamePasswordToken that I'd
have to generate an AuthenticationInfo instance for; why would I want to
enumerate all the principals for the subject that
this UsernamePasswordToken belongs to? What are these used for later down
the line?
As far as I understand, having the AuthenticatingRealm successfully
fabricate an AuthenticationInfo merely means that authentication was
successful. Is this correct?
What is point of fetching a collection of principals?
I hope that my questions are not too overwhelming, and that you can find
some time to explain this a little further to me.
Thank you very much in advance,
Maarten