4

I am in the process of implementing a solution that has an MVC client (lets call this CLIENT at localhost:4077/) with a WebAPI service (called API at localhost:4078/)

I have implemented OWIN OAuth in the API but wanted to know whether the OWIN could be implemented in a separate solution (lets call it AUTH at localhost:4079/token) to generate the token for the CLIENT, then the CLIENT passes this to the API (as the Bearer authorisation token)

The reason i am querying this is that there is likely to be additional WebAPI services that will be accessed by the CLIENT and i'd like to use OWIN between the client and all API services.

The issue is i am not sure if the token generated by the AUTH service could be used to authorise all requests on the CLIENT and all API services.

Has anyone implemented anything like this and if so could you provide an example, i am pretty new to OWIN and OAUTH so any help would be greatly appreciated

Neil Stevens
  • 3,534
  • 6
  • 42
  • 71

1 Answers1

6

Separating the authorization server from the resource server is extremely easy: it will even work without any extra code if you use IIS and if you have configured identical machine keys on both applications/servers.

Supporting multiple resource servers is a bit harder to implement with the OWIN OAuth2 server if you need to select which endpoints an access token can gain access to. If you don't care about that, just configure all your resource servers with the same machine keys, and you'll be able to access all your APIs with the same tokens.

To have more control over the endpoints that can be used with an access token, you should take a look at AspNet.Security.OpenIdConnect.Server - a fork of the OAuth2 server that comes with OWIN/Katana - that natively supports this scenario: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server.

It's relatively easy to set up:

Add a new middleware issuing tokens in your authorization server application (in Startup.cs):

app.UseOpenIdConnectServer(new OpenIdConnectServerOptions
{
    Provider = new AuthorizationProvider()
});

Add new middleware validating access tokens in your different API servers (in Startup.cs):

app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
    // AllowedAudiences MUST contain the absolute URL of your API.
    AllowedAudiences = new[] { "http://localhost:11111/" },

    // X509CertificateSecurityTokenProvider MUST be initialized with an issuer corresponding to the absolute URL of the authorization server.
    IssuerSecurityTokenProviders = new[] { new X509CertificateSecurityTokenProvider("http://localhost:50000/", certificate) }
});

app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
    // AllowedAudiences MUST contain the absolute URL of your API.
    AllowedAudiences = new[] { "http://localhost:22222/" },

    // X509CertificateSecurityTokenProvider MUST be initialized with an issuer corresponding to the absolute URL of the authorization server.
    IssuerSecurityTokenProviders = new[] { new X509CertificateSecurityTokenProvider("http://localhost:50000/", certificate) }
});

Finally, add a new OpenID Connect client middleware in your client app (in Startup.cs):

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    // Some essential parameters have been omitted for brevity.
    // See https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/dev/samples/Mvc/Mvc.Client/Startup.cs for more information

    // Authority MUST correspond to the absolute URL of the authorization server.
    Authority = "http://localhost:50000/",

    // Resource represents the different endpoints the
    // access token should be issued for (values must be space-delimited).
    // In this case, the access token will be requested for both APIs.
    Resource = "http://localhost:11111/ http://localhost:22222/",
});

You can have a look at this sample for more information: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/dev/samples/Mvc/

It doesn't use multiple resource servers, but it shouldn't be hard to adapt it using the different steps I mentioned. Feel free to ping me if you need help.

Kévin Chalet
  • 39,509
  • 7
  • 121
  • 131
  • 1
    Thanks for this, i tried this and it worked really well, i also came across a set of articles by Taiseer Joudah (http://bitoftech.net/2014/09/24/decouple-owin-authorization-server-resource-server-oauth-2-0-web-api/), needed to follow the article from Part 1 (i skipped the angular steps for me they were not relevant) and managed to get a setup with a auth service and two WebAPI project that accessed a secured controller passing the Bearer authentication header – Neil Stevens Jun 20 '15 at 20:32
  • Nice! Out of curiosity, do you prefer the solution I suggested or Taiseer Joudah's approach, that uses the OAuth2 authorization server built in Katana with some tweaking? – Kévin Chalet Jun 20 '15 at 20:54
  • Ah man your putting me on the spot! I like both approaches but if im honest Taiseer Joudah's approach was simpler to implement and needed just two lines of code adding to `Startup.cs` for each additional WebAPI service – Neil Stevens Jun 20 '15 at 21:01
  • No problem. If you see parts that could be simplified, don't hesitate to ping me ;) – Kévin Chalet Jun 20 '15 at 21:16
  • I realize my answer wasn't clear enough: I updated it to mention that using the same access tokens for all your APIs can be implemented using machine keys. The rest of my answer still applies if you want to select which endpoints your access tokens will be able to gain access to (i.e an access token can be used to call "API 1", but not "API 2"... or both ones if you want to). Taiseer Joudah's approach only supports the first case. – Kévin Chalet Jun 20 '15 at 21:57
  • Also note that you can't use his solution with resource servers that doesn't use the OAuth2 bearer middleware (basically, every non-OWIN app) or with resource servers that are not under your control, because you can't share your machine keys. – Kévin Chalet Jun 20 '15 at 22:04