dasiths / NEasyAuthMiddleware

Azure App Service Authentication (EasyAuth) middleware for ASP.NET CORE with fully customizable components and support for local debugging
MIT License
14 stars 6 forks source link

Testing from Postman always returns 401 #5

Closed HeinA closed 4 years ago

HeinA commented 4 years ago

'ello

While testing with postman, I always get a 401 Unauthorized.

I'm testing this for an Api that I want to call from Unity using Google sign-in.

I pass the Authentication Token I get from the ".auth/login/google" endpoint on my App Service to my API in the X-ZUMO-AUTH header.

Am I misunderstanding something?

Thanx Hein

dasiths commented 4 years ago

I can't say for sure without looking at your code. Is the 401 being returned from your own code (i.e. Controller with Authorization attribute) or from a downstream API?

The best way to test it would be to do something like this in your code

    [Route("api/[controller]")]
    [ApiController]
    public class AuthTestController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<object> Get()
        {
            var headers = Request.Headers
                .Select(h => new {name = h.Key, value = h.Value})
                .ToList();

            var userClaims = HttpContext.User.Claims
                .Select(claim => new {name = claim.Type, value = claim.Value})
                .ToList();

            return new
            {
                Headers = headers,
                Claims = userClaims
            };
        }
    }
  1. Follow the ReadMe file from this repo and add NEasyAuthMiddleware in. Then add the above code snippet for the controller.
  2. Deploy it to an app service. (Configured to work with Google federated sign in)
  3. Then hit https://yourwebsitename.azurewebsites.net/api/AuthTest and see what it returns. If it has all the claims and headers you expect then we can be certain the middleware works.
  4. If there is a header but isn't mapped to a claim then you will have have to write a custom mapper as shown in the readme.
  5. The token will be in a claim or in the header hence you won't need to call .auth/login/google to get it AFAIK. You can then simply attach that as an authorization header in a downstream API call.
HeinA commented 4 years ago

Hi there. Thank you very much for your prompt reply.

You are correct. There are no Claims...

All I really need to do is verify that the user is authenticated.

I have tried creating a claims mapper like such: public class ClaimsMapper : IClaimMapper { public ClaimMapResult Map(IHeaderDictionary headers) { List list = new List(); list.Add(new Claim(ClaimTypes.Role, "Default")); return new ClaimMapResult(ClaimMapResultType.Success, list); } }

It still returns an empty claims array though...

This is the result of the above controller:

{ "headers": [ { "name": "Connection", "value": [ "Keep-Alive" ] }, { "name": "Accept", "value": [ "application/json, text/json, text/x-json, text/javascript, application/xml, text/xml" ] }, { "name": "Accept-Encoding", "value": [ "gzip, deflate" ] }, { "name": "Host", "value": [ "xafari.azurewebsites.net" ] }, { "name": "Max-Forwards", "value": [ "10" ] }, { "name": "User-Agent", "value": [ "RestSharp/106.11.4.0" ] }, { "name": "Request-Id", "value": [ "|ca86c5f9-44d61421fd35a6bd.1." ] }, { "name": "Content-Length", "value": [ "0" ] }, { "name": "X-Client-IP", "value": [ "197.188.220.105" ] }, { "name": "X-Client-Port", "value": [ "9509" ] }, { "name": "X-ZUMO-AUTH", "value": [ "blah" ] }, { "name": "X-WAWS-Unencoded-URL", "value": [ "/authtest" ] }, { "name": "CLIENT-IP", "value": [ "197.188.220.105:9509" ] }, { "name": "X-ARR-LOG-ID", "value": [ "4cdcf683-7dd2-4249-b4d0-72ab7c5c38b2" ] }, { "name": "DISGUISED-HOST", "value": [ "xafari.azurewebsites.net" ] }, { "name": "X-SITE-DEPLOYMENT-ID", "value": [ "Xafari" ] }, { "name": "WAS-DEFAULT-HOSTNAME", "value": [ "xafari.azurewebsites.net" ] }, { "name": "X-Original-URL", "value": [ "/authtest" ] }, { "name": "X-Original-Proto", "value": [ "http" ] }, { "name": "X-ARR-SSL", "value": [ "2048|256|C=US, S=Washington, L=Redmond, O=Microsoft Corporation, OU=Microsoft IT, CN=Microsoft IT TLS CA 5|CN=*.azurewebsites.net" ] }, { "name": "X-AppService-Proto", "value": [ "https" ] }, { "name": "X-Forwarded-TlsVersion", "value": [ "1.2" ] }, { "name": "X-MS-CLIENT-PRINCIPAL-ID", "value": [ "sid:cdaf4c83e38c87e40ad0a0fb202232ed" ] }, { "name": "X-MS-CLIENT-PRINCIPAL-IDP", "value": [ "google" ] }, { "name": "X-MS-CLIENT-PRINCIPAL", "value": [ "eyJhdXRoX3R...dGl0eVwvY2xhaW1zXC9yb2xlIn0=" ] }, { "name": "X-MS-TOKEN-GOOGLE-ID-TOKEN", "value": [ "blah" ] }, { "name": "X-Original-For", "value": [ "[::ffff:172.16.0.5]:37122" ] } ], "claims": [] }

On Mon, Aug 3, 2020 at 4:39 AM Dasith Wijesiriwardena < notifications@github.com> wrote:

I can't say for sure without looking at your code. Is the 401 being returned from your own code (i.e. Controller with Authorization attribute) or from a downstream API?

The best way to test it would be to do something like this in your code

[Route("api/[controller]")]
[ApiController]
public class AuthTestController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public ActionResult<object> Get()
    {
        var headers = Request.Headers
            .Select(h => new {name = h.Key, value = h.Value})
            .ToList();

        var userClaims = HttpContext.User.Claims
            .Select(claim => new {name = claim.Type, value = claim.Value})
            .ToList();

        return new
        {
            Headers = headers,
            Claims = userClaims
        };
    }
}
  1. Follow the ReadMe file from this repo and add NEasyAuthMiddleware in. Then add the above code snippet for the controller.
  2. Deploy it to an app service. (Configured to work with Google federated sign in)
  3. Then hit https://yourwebsitename.azurewebsites.net/api/AuthTest and see what it returns. If it has all the claims and headers you expect then we can be certain the middleware works.
  4. If there is a header but isn't mapped to a claim then you will have have to write a custom mapper as shown in the readme.
  5. The token will be in a claim or in the header hence you won't need to call .auth/login/google to get it AFAIK. You can then simply attach that as an authorization header in a downstream API call.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/dasiths/NEasyAuthMiddleware/issues/5#issuecomment-667772653, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJBC7OUSAPVRSDICOMVRXDR6YPM5ANCNFSM4PSWWSUQ .

dasiths commented 4 years ago

Don't paste your tokens in a public arena like this. Someone can steal your identity using it.

Also the claims coming from the payload you posted is

"claims": [
    {
      "typ": "stable_sid",
      "val": "sid:5bf302a89ac327f4050b216dc2b61629"
    },
    {
      "typ": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
      "val": "sid:cdaf4c83e38c87e40ad0a0fb202232ed"
    },
    {
      "typ": "http://schemas.microsoft.com/identity/claims/identityprovider",
      "val": "google"
    },
    {
      "typ": "ver",
      "val": "3"
    },
    {
      "typ": "nbf",
      "val": "1596442430"
    },
    {
      "typ": "exp",
      "val": "1599034430"
    },
    {
      "typ": "iat",
      "val": "1596442430"
    },
    {
      "typ": "iss",
      "val": "https://xafari.azurewebsites.net/"
    },
    {
      "typ": "aud",
      "val": "https://xafari.azurewebsites.net/"
    }
  ],
HeinA commented 4 years ago

Thank you very much.

I had to add

app.UseAuthorization();

in my Configure Startup method.

I misread Authentication for Authorization.

This is a fantastic library, thanx. I looked long and hard to find something that does this :)

On Mon, Aug 3, 2020 at 11:30 AM Dasith Wijesiriwardena < notifications@github.com> wrote:

Don't paste your tokens in a public arena like this. Someone can steal your identity using it.

Did you register your ClaimsMapper in the DI container? If not it won't get picked up?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/dasiths/NEasyAuthMiddleware/issues/5#issuecomment-667916506, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJBC7PVG7VK7CHSRY35P5LR6Z7TTANCNFSM4PSWWSUQ .

dasiths commented 4 years ago

Glad you got it sorted.

dasiths commented 4 years ago

Thank you very much. I had to add app.UseAuthorization(); in my Configure Startup method. I misread Authentication for Authorization. This is a fantastic library, thanx. I looked long and hard to find something that does this :) On Mon, Aug 3, 2020 at 11:30 AM Dasith Wijesiriwardena < @.***> wrote: Don't paste your tokens in a public arena like this. Someone can steal your identity using it. Did you register your ClaimsMapper in the DI container? If not it won't get picked up? — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#5 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJBC7PVG7VK7CHSRY35P5LR6Z7TTANCNFSM4PSWWSUQ .

I didn't realize you were using AspnetCore 3.0+

You will have to follow this guide to upgrade my example. https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio#migrate-startupconfigure

So you need both .UseAuthentication and .UseAuthorization