Hi Demis,
in your documentation you mention a third party plugin to use ServiceStack together with IdentityServer. With your JwtProviderReader it’s actually already possible:
host.Plugins.Add(new AuthFeature(() => new AuthUserSession(), new[] { new JwtAuthProviderReaderCustom() { PublicKeyXml = _config.TokenSigningCertXml, // may also be fetched from https://demo.identityserver.io/.well-known/openid-configuration/jwks HashAlgorithm = "RS256", Audience = "xxxxx", ServiceRoutes = new Dictionary() // it throws a NullRef if not initialized :( } } ));
I’d propose to mention this in your documentation.
There are 3 small things to fix:
-
ServiceRoutes initialization
JwtAuthProviderReader throws if not initialized. -
“Aud” check should be contains and not ==
The RFC (RFC 7519 - JSON Web Token (JWT))
The “aud” (audience) claim identifies the recipients that the JWT is
intended for. Each principal intended to process the JWT MUST
identify itself with a value in the audience claim
if (jwtPayload.TryGetValue("aud", out audience)) { if (!audience.Contains(Audience)) // <-- contains throw new TokenException("Invalid Audience: " + audience); }
But i also see that contains might be problematic. But since in the RFC there is no separator defined, i think it’s the only viable option.
- Map values to session
Claims are defined here: JSON Web Token (JWT)
Since you call session.PopulateFromMap(jwtPayload); in CreateSessionFromPayload, it would make sense to map those Fields also in PopulateFromMap() like you do in JwtAuthProvider.CreateJwtPayload.
In our case we had to fork JwtAuthProviderReader to map auth_time, nickname, given_name, family_name.
What dou you think about those changes?
I could do a PR, but just if you are interested…
cheers
tobi