26

I am attempting to decouple my auth and resource server. I am following the example provided in this tutorial:

http://bitoftech.net/2014/09/24/decouple-owin-authorization-server-resource-server-oauth-2-0-web-api/

This is the code in my Startup.cs in my auth server:

using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AuthServer.Web
{
   public class xxxxx
   {
      public void Configuration(IAppBuilder app) {
         ConfigureOAuth(app);
      }

      public void ConfigureOAuth(IAppBuilder app)
      {
         OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
         {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider()
         };

         // Token Generation
         app.UseOAuthAuthorizationServer(OAuthServerOptions);
         app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

      }
   }
}

This is the startup.cs in my resource server (i.e. my sample Web api application):

using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AuthTestApi.Web
{
   public class Startup
   {
      public void Configuration(IAppBuilder app)
      {
         app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
         app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
      }      
   }
}

When I post the following request to the "\token" endpoint of my auth server I sucessfully receive a token:

{
access_token: "PszrzJUtQUhX42GMryWjZiVHuKiJ9yCVH_1tZURumtC5mTj2tpuRDF3tXcN_VNIYuXY40IG0K7W3KASfJ9DlNIU2jMOkL2U5oEAXLNRRQuNYdEJ7dMPb14nW19JIaM4BMk00xfQ8MFRw0p6-uoh0-e-Q6iAiTwDNN3F7bYMF9qm874qhLWEcOt6dWQgwpdDUVPDi7F07-Ck0zAs48Dg5w4q93vDpFaQMrziJg9aaxN8",
token_type: "bearer",
expires_in: 86399
}

When I post the following request to my controller I receive the "Authorization has been denied for this request" error message?

GET /api/Test HTTP/1.1
Host: localhost:63305
Accept: application/json
Content-Type: application/json
Authorization: Bearer PszrzJUtQUhX42GMryWjZiVHuKiJ9yCVH_1tZURumtC5mTj2tpuRDF3tXcN_VNIYuXY40IG0K7W3KASfJ9DlNIU2jMOkL2U5oEAXLNRRQuNYdEJ7dMPb14nW19JIaM4BMk00xfQ8MFRw0p6-uoh0-e-Q6iAiTwDNN3F7bYMF9qm874qhLWEcOt6dWQgwpdDUVPDi7F07-Ck0zAs48Dg5w4q93vDpFaQMrziJg9aaxN8
Cache-Control: no-cache
Postman-Token: aeca8515-70b1-ef2c-f317-bf66136dccab

My auth server and resource / web api projects are in different solutions and are running on different ports (...not sure if that matters but thought Id mention it).

At this point these 2 projects are making use of oAuth OWIN middleware (and has very little custom code). The middleware is blackbox somewhat and just need some assistance in figuring out why I am receiving this error message.

Also note that the I am running both servers in two Visual Studio 2013 Web application projects that are in different VS 2013 solutions that are running on different ports. I am not sure if that matters but thought I would mention it.

Thanks in advance.

user1870738
  • 503
  • 1
  • 8
  • 14
  • Have you unified the machinekey tags in both webconfig files? – Xavier Egea Oct 20 '14 at 07:47
  • Are you making use of Owin.SelfHost for one solution and Owin.SystemWeb for the other? ASP.Net makes use of MachineKey whilest Owin.SelfHost makes use of DPAPI. (As far as I know) MachineKey and DPAPI don't play well with each other. Try hosting both projects using Owin.SystemWeb – Dwayne Hinterlang Jan 07 '15 at 08:42
  • @user1870738.THANKS FOR HELP.your solution works. – Prince May 25 '18 at 12:54

8 Answers8

29

I just came across the same problem and found the solution:

You need to register the OAuth Token Generator and OAuth Token Consumer things before WebAPI is registered.

Kind of makes sense if you think of this as a pipeline, where Authentication/Authorization should come before any request handling by the controllers.

TL;DR: Change

appBuilder.UseWebApi(config);

this.ConfigureOAuthTokenGenerator(appBuilder);
this.ConfigureOAuthConsumer(appBuilder);

To

this.ConfigureOAuthTokenGenerator(appBuilder);
this.ConfigureOAuthConsumer(appBuilder);

appBuilder.UseWebApi(config);
cguedel
  • 1,092
  • 1
  • 14
  • 28
14

I was also receiving the error message 'Authorization has been denied for this request', although I don't have separate auth and resource servers.

I am using Ninject's OwinHost and had it configured in Startup before configuring OAuth, as follows:

public void Configuration(IAppBuilder app)
{
    var config = new HttpConfiguration();

    app.UseNinjectMiddleware(() =>
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());
        return kernel;
    }).UseNinjectWebApi(config);

    ConfigureOAuth(app);

    WebApiConfig.Register(config);
    app.UseCors(CorsOptions.AllowAll);
    app.UseWebApi(config);
}

I found that moving the Ninject configuration to the end resolved the problem, like so:

public void Configuration(IAppBuilder app)
{
    var config = new HttpConfiguration();

    ConfigureOAuth(app);

    WebApiConfig.Register(config);
    app.UseCors(CorsOptions.AllowAll);
    app.UseWebApi(config);

    app.UseNinjectMiddleware(() =>
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());
        return kernel;
    }).UseNinjectWebApi(config);
}

Maybe your problem is to do with the startup order of your middleware.

gwhn
  • 2,723
  • 4
  • 23
  • 26
  • 8
    +1 - I had a similar problem where my auth and resource server were one and the same project and all my tokens were being rejected. Apparently the code in ConfigureOAuth() needs to be executed before calling app.UseWebApi(config). Very confusing. – efdee Nov 16 '14 at 16:32
  • @efdee bloody hell, we've collectively spent several hours trying to figure out what is wrong. and yet my team still won't admit that web api stinks and use Nancy or SimpleWeb instead :( – Tomasz Pluskiewicz Feb 25 '15 at 15:51
  • @TomaszPluskiewicz I've had the same issue for the past day & half, searched everywhere, only to realize order of operations is important for UserWebAPI. But I'd still agree with your team, I'm not quiet ready to drop an entire framework because of MY lack of knowledge. Not implying its the same for you. – OverMars Feb 02 '18 at 19:21
5

I was facing exactly the same problem in the last couple of days, although I host both application on the same machine (different ports) but it didn't work without adding machine key both web.config files and make sure that the same packages version number installed in both applications

Islam El-Khayat
  • 406
  • 5
  • 14
  • For reference, Appendix A on this [Microsoft KB](http://support.microsoft.com/kb/2915218#AppendixA) article explains how to generate the machineKey tag for the web.config files – feganmeister Jun 14 '17 at 11:34
4

In my post I was clear that you need to override the machineKey node for both APIs (Authorization Server and Resource Server) and share the same machineKey between both web.config files. How do you host those 2 different projects? they are on the same machine or different machines? Please go back to step 5 from the post and check how you can achieve this.

Taiseer Joudeh
  • 8,953
  • 1
  • 41
  • 45
  • Thanks for the quick response. I have both applications (auth and resource server) running in 2 different Visual Studio solutions on my dev machine. They are running on 2 different ports. Let me know if I need to use the same machine key in my Web.config. I was thinking that I would not have to only because though they are not running on the same port they are on the same machine. – user1870738 Oct 20 '14 at 16:09
  • 7
    Strange, as long as they are on the same machine then they are sharing the same machine.config file and same machineKey. No need to do anything in Web.config. Can you make sure they are both using the same version of Microsoft.Owin.Security.OAuth? – Taiseer Joudeh Oct 20 '14 at 22:18
  • 5
    I wish I could up vote the prior comment 1000 times. My Microsoft.Owin.Security.OAuth version on the auth server was 3.0.1, resource server was 3.0.0. Been pulling my hair out for hours, once I got them on the same version it worked like a charm! – BBauer42 Oct 05 '15 at 20:41
  • 1
    I, too would up vote that comment 1000 times. Just spend about 5 hours trying to figure out this issue. to discover it was a Midrosoft.Owin.Security.OAuth version issue – Franklin Oct 12 '15 at 15:04
  • holy smokes !! WIsh I had found this about 3 hrs ago ! definitely the version mismatch for me as well... – Greg Foote Jan 15 '16 at 22:48
3

For me, the problem was a mismatched version number in Owin packeges:

 <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
  </dependentAssembly>

After updating the required older packages, everything worked like a charm. :)

Aage
  • 5,932
  • 2
  • 32
  • 57
Kádi
  • 2,796
  • 1
  • 16
  • 22
  • +1 In my case I've to copied the **Package.config** and full Tag in **web.config** from the original source code into my new resource server – Jayendran Oct 10 '17 at 11:21
3

June 6 2018 update - using the latest WebAPI and OWIN packages. I've been banging my head against this problem for more than I would like to admit. None of the above suggestions worked for me, things suddenly started working once I added a certain project dependency that I wasn't even using in my code: the Microsoft.Owin.Host.SystemWeb NuGet package. This setup is way too finicky and black-boxed for my taste, I don't know why it works like this, but here's what I did.

The minimal setup that I needed for the resource service (the authentication/token service was already setup):

  • add references to Microsoft.Owin.Security.Oauth and Microsoft.Owin.Host.SystemWeb
  • create a startup.cs file with the following content:

    using Microsoft.Owin;
    using Owin;
    using Microsoft.Owin.Security.OAuth;
    
    [assembly: OwinStartup(typeof(MyProject.Startup))]
    
    namespace MyProject
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions{ });
            }
        }
    }
    
  • Add the following to your Web.config file in the <appSettings> section

<add key="owin:appStartup" value="MyProject.Startup" />
Mihai Coman
  • 354
  • 2
  • 6
  • If I could buy you a beer, I would. This was the only solution to my problem after losing an entire day! Cheers! – JoniVR Sep 08 '20 at 15:31
1

In your OwinStartup class, IAppBuilder.UseOAuthBearerTokens() needs to be called BEFORE IAppBuilder.UseWebApi()

public void Configuration(IAppBuilder app)
{
    app.UseOAuthBearerTokens(...);
    app.UseWebApi(...);
}
0

Running web applications in IIS with different pool you'll get different keys. So, you should run auth and resource applications with the same application pool. Check this https://gyorgybalassy.wordpress.com/2013/12/07/how-unique-is-your-machine-key/

fSmooth
  • 21
  • 5