I am using Visual Studio 2015 Enterprise Update 1 and ASP.NET 5 rc1-final to build an endpoint that both issues and consumes JWT tokens as described in detail here. In this approach we have a single project that 'does it all' - the project uses OIDC to issue tokens, JWT bearer authentication to validate them and then guards access to various controllers using the Authorize attribute - all in the same project.
Now we would like to refactor this solution by creating an OIDC authorization & authentication endpoint that only issues and validates tokens. Then we want 'n' additional endpoints that rely on that OIDC endpoint as a central authority for authenticating tokens. This will allow us to stand up additional endpoints on our growing service backbone without having to code the authorization & authentication into every endpoint.
While I understand how to configure OIDC to issue tokens from one endpoint, it's not entirely clear how I would point my other endpoint to the OIDC endpoint for token authentication. Presently JWT authentication and OIDC are simultaneously configured in the middleware 'Configure' method so I'm guessing perhaps on all the subordinate sites I would have a small piece of code in calling app.UseJwtBearerAuthentication simply pointing the JWT middleware to the OIDC endpoint? If this is the case there's still a bit of magic taking place with the app.UseJwtBearerAuthentication that uses OIDC to allow IdentityModel to use HTTP, so I'm not clear if I would need this on the subordinate servers also.
Any advice on how to establish a single OIDC authorization & authentication endpoint and then have 'n' subordinate endpoints point to that endpoint for authentication of JWT tokens would be very much appreciated.
Separating the resource server role (i.e the API) from the authorization server role is definitely possible with ASOS.
When opting for JWT tokens (instead of the default encrypted tokens), you need to ensure the audience is correctly added to the authentication ticket by calling ticket.SetResources, so the JWT access token gets the appropriate aud claim, containing the identifier associated with your resource server (i.e API):
public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context) {
var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
identity.AddClaim(ClaimTypes.NameIdentifier, "[unique identifier]");
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
// Call SetResources with the list of resource servers
// the access token should be issued for.
ticket.SetResources("resource_server_1");
// Call SetScopes with the list of scopes you want to grant.
ticket.SetScopes("profile", "offline_access");
context.Validate(ticket);
return Task.FromResult(0);
}
In your API app, you just have to set the options.Audience property with the identifier used in the authorization server, and it should work:
app.UseJwtBearerAuthentication(new JwtBearerOptions {
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Audience = "resource_server_1",
Authority = "http://localhost:61854"
});
I would have a small piece of code in calling app.UseJwtBearerAuthentication simply pointing the JWT middleware to the OIDC endpoint? If this is the case there's still a bit of magic taking place with the app.UseJwtBearerAuthentication that uses OIDC to allow IdentityModel to use HTTP, so I'm not clear if I would need this on the subordinate servers also.
The JWT bearer middleware automatically retrieves the cryptographic key used to sign the access token from the authorization server mentioned in the options.Authority property, by making an HTTP call to the configuration metadata endpoint: you don't have to configure anything, even if the API project is separated from the authorization server app.
Related
Currently I have an SPA with multiple springboot microservices at the back (Resource Servers). Authentication and Authorization happens in the back using a Spring Oauth2 Server that serves a "Login Page" (Consent Screen) . Inside the Oauth server there is a ldapAuthentication provider that delegates authentication to an Active Directory and the rest (user detail and authorities) is fetched from a jdbc source from a custom data model (groups and privileges).
I have the requirement to start using Okta (enterprise). Conceptually speaking, do I have to remove completely the Spring Oauth Server and do everything with Okta regarding Authentication and Authorization? What would be the flow? What happens with the Bearer Token that I currently use? What happens with the introspection of each resource server when applying security access to requests? I am pretty confused what should be the Spring solution for Okta comming from a Spring Oauth Server.
Yes, Okta and Spring OAuth server are both authorization-servers, so you'll probably replace one with the other. The flow will be the same standard OAuth2 authorization-code flow:
"rich" client redirects users to authorization-server for authentication (Okta instead of spring authorization-server)
authorization-server redirects users back to "rich" client with authorization code
"rich" client exchanges authorization-code for access and optionally refresh and ID tokens
"rich" client sends request to resource-servers with access-token as Bearer Authorization header
resource-servers validate access-tokens and retrieves token claims (either with JWT decoder or introspection) and then evaluates if access should be granted based on token claims
You'll have to refer to Okta docs to add required roles (or groups or authorities and whatever you need in your resource-servers security expressions and that is stored in your LDAP and "JDBC storage") to Okta access-tokens.
If you really have configured your resource-servers with token introspection, you might have to switch to JWT decoding (I haven't search much, but it seams that Okta's introspection endpoint just returns a boolean: isTokenValid). You'll save a lot of resources in the process as JWT validation & decoding happens on resource-server only (it does not require a round-trip to authorization-server for each request as introspection)
You can replace your Spring OAuth server with Okta Authorization Server, which will require all your micro-services to change their configuration to do the introspection against Okta endpoints. Bearer tokens would be minted by Okta too.
In my project I use the identity server 4, an SPA (Angular) and a protected API (PHP). I decided me to use the reference token. My Client (SPA) works with implicit flow (is it correct not to use a client secret?) And gets the access token after login (call the authorize endpoint). After that the SPA have to send the token to the API so the API can ask the identity server 4 (introspection endpoint), if the access token is correct and the API can get access to the userĀ“s information.
Now I want to know, how to secure the communication. Because the access token has no information in it, is it necessary to send him with jwt to the API or is it enough with a normal JSON send? As I understand the API must call the introspection endpoint with jwt bearer.
Is this method secure or what else should I do?
There is no such requirement - the API to call the introspection with a JWT. If the API is set to work with JWT's it will just verify the signature of the token with the public key from IDS. If it is set to work with reference token - it will call the introspection, to get the user info (which is the payload of the JWT). Reference tokens documentation.
Your API needs to be protected with its ID and Secret, so that you can call the introspection endpoint.
When calling it you send the reference token (it is still an access token, but it is not a JWT), the client_id and the client_secret. The content-type of the request should be application/x-www-form-urlencoded and it should be POST.
The response from the introspection endpoint is the user info.
No need of additional security - the client ID and Secret are the security, and the call is made server-to-server from API to IDS (assuming you are behind https of course)
I've been going through this tutorial which shows how to secure a single page application using several scenarios going from simple to our own Authorization Server that delegates authentication to a provider. The first scenario uses the Authorization Code Grant to log the user in.
Suppose we replace Facebook's OAuth Server with our own in this case and configure it to return a JWT token.
Which OAuth flow should the SPA use if it wants to use the JWT token to secure requests through an edge server that load balances between resources servers?
Also how should spring boot / spring security be configured if we want to use the JWT token to replace the replace the default JSESSION and CSRF support in spring? IIUC the JWT token can be used as a replacement to both of these features.
Update
Based on Manish's answer assuming we are using OAuth 2 implicit flow we:
Put the #EnableResourceServer annotation on the Resource Server
Use an OpenID Connect client to implement the implicity flow
So once this is done are POST request secure assuming each request includes the JWT token as a Bearer Header, or do we need to also configure CSRF?
It will depend on how much your application is sensitive to security but Implicit flow is recommended for pubic client (SPA).
Tutorial is based Authorization Code flow and if you will replace Facebook with your STS, it will still use Authorization Code flow because #EnableOAuth2Sso store the JWT token on server and send the cookie to browser and it also uses refresh token to get the new JWT token. It is a customize flow to implement the Authorization Code flow with public client (SPA) based on API gateway pattern.
To implement the implicit flow - Do not use the #EnableOAuth2Sso at server side, just expose the REST API and secure it with #EnableResourceServer. And you need to use the oidc-client to implement the implicit flow link is here https://github.com/IdentityModel/oidc-client-js
CSRF protection is only required if you will store JWT token or session identifier in the browser's cookie.
I am developing an AspNetCore 2 app that has web views alongside an API (prefixed with /api) and i am trying to have the web views be authenticated using OpenIdConnect + cookies, while the /api prefixed routes be authenticated with JWT tokens (for mobile app compatibility).
So far i've managed to register and configure the cookies, OpenIdConnect and JWT middlewares using this code:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie()
.AddOpenIdConnect(options => {
var optionsSetup = new OpenIdConnectOptionsSetup(b2cOptions);
optionsSetup.Configure(options);
});
services.AddAuthentication()
.AddJwtBearer(options => {
var optionsSetup = new JWTBearerOptionsSetup(b2cOptions);
optionsSetup.Configure(options);
});
Along with this line on the Configure method:
app.UseAuthentication();
OpenIdConnectOptionsSetup is taken from (with slight modifications) the aspnetcore AD B2C sample repositories.
JWTBearerOptionsSetup is a refactor from the aspnetcore AD B2C sample repo to extract the JWT configuration code into an external class.
Right now AJAX calls to an /api endpoint are being met with an OpenId redirect to our AD's login policy endpoint, so the Cookie/OpenIdConnect middleware are handling those. I need a way to make /api go straight into the JWTBearer middleware instead.
Is this possible? Must i separate the web and the API projects?
I would recommend that you separate the web and the api into separate services, because otherwise it will be harder to reason about the behavior of the system. Troubleshooting the system will also be easier.
Both the cookie and JWtBearer handler will try to create the ClaimsPrincipal user object in your system, either from the session cookie or from the access-token.
Perhaps this blog post can give you some hints:
Combining Bearer Token and Cookie Authentication in ASP.NET
I've begun an implementation using the OpenID Connect Implicit Flow - I've retrieved my access token and ID token in my browser based javascript app, and now I need to protect the resource on my ASP.NET Core Web API so it can only be accessed via a valid access token from a user with a specific claim.
What middleware do I use to validate the token(s) and determine the user and their claims so I can then allow or deny them access to the resource they are requesting?
I've looked at OpenIdConnectAuthentication middleware, however the only implementation examples I've seen use a SignInScheme of "Cookies", not the Bearer token that my js app is providing.
Thanks
What middleware do I use to validate the token(s) and determine the user and their claims so I can then allow or deny them access to the resource they are requesting?
If your authorization server issues JWT tokens, you can use the JWT bearer middleware developed by the ASP.NET team: https://github.com/aspnet/Security/tree/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer.
app.UseJwtBearerAuthentication(new JwtBearerOptions {
Authority = Configuration["jwt:authority"],
Audience = Configuration["jwt:audience"]
});
You can find a sample here: https://github.com/aspnet/Security/tree/dev/samples/JwtBearerSample.