0
votes

I'm trying to do custom OAuth2 authorization server that will support Resource Owner Password Credentials flow. The authorization server is an WebAPI application hosted in IIS7.5.

I have configured startup class where I register custom OAuthServerProvider (AtcAuthorizationServerProvider).

[assembly: OwinStartup(typeof(ATC.WebApi.AuthorizationServer.Startup))]

namespace ATC.WebApi.AuthorizationServer
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureOAuth(app);

            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
            app.UseWebApi(config);

            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        }

        public void ConfigureOAuth(IAppBuilder app)
        {
            OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
                Provider = new AtcAuthorizationServerProvider(),
                RefreshTokenProvider = new AtcRefreshTokenProvider(),
                AuthenticationMode = AuthenticationMode.Passive
            };

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

In my custom provider class, I override ValidateClientAuthentication() function where I accept both client credentials receiving ways (in Body and in Authorization header).

public class AtcAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId = string.Empty;
            string clientSecret = string.Empty;

            // get client credentials from header or from body
            if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
            {
                context.TryGetFormCredentials(out clientId, out clientSecret);
            }
//rest of code

Everything works fine when I send client_id and client_secret in body.

POST /ATC.WebApi.AuthorizationServer/token HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache

grant_type=password&password=123456&username=myUser&client_id=myClient&client_secret=123%40abc

I get access token successfully.

{
  "access_token": "3Fk_Ps10i45uL0zeCzIpvEh2WHKE8iJVNtKJ2XGWcQWXsT9jllKf...",
  "token_type": "bearer",
  "expires_in": 1799,
  "refresh_token": "4c1097d17dd14df5ac1c5842e089a88e",
  "as:client_id": "myClient"
}

However, if I use DotNetOpenAuth.OAuth2.WebServerClient which passes client_id and client_secret in Authorization header I will recieve 401.1 - Unauthorized HTTP response. I have found out that the ValidateClientAuthentication() is not fired.

Request than looks like this:

POST /ATC.WebApi.AuthorizationServer/token HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic C16b34lUjEyM0BhYmM=
Cache-Control: no-cache

grant_type=password&password=123456&username=myUser

The question is how to persuade probably the OWIN middle-ware firing my custom Provider in this case?

1

1 Answers

0
votes

Well, I finally found out where is the trouble. There was Basic authentication allowed in my IIS, so IIS got the request and tried to Authenticate User which failed and IIS returned 401 Unauthorized immediately. So my OWIN middleware even did not receive the request to processing.