Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Policy-based authorization, How to configure the policy name for the ReRoute #265

Closed
yiluomyt opened this issue Mar 7, 2018 · 6 comments
Labels
question Initially seen a question could become a new feature or bug or closed ;)

Comments

@yiluomyt
Copy link

yiluomyt commented Mar 7, 2018

Expected Behavior / New Feature

I would like to override the AuthorisationMiddleware to use the policy-based authorization.

Actual Behavior / Motivation for New Feautre

According to the document, now I try this way to achieve.

AuthorisationMiddleware = async (ctx, next) =>
{
    // How can I configure the policy name for the ReRoute
    string policyName = "admin";
    IAuthorizationService authorizationService = ctx.HttpContext.RequestServices.GetService<IAuthorizationService>();
    var result = await authorizationService.AuthorizeAsync(ctx.HttpContext.User, policyName);
    if (result.Succeeded)
    {
        await next.Invoke();
    }
    else
    {
        ctx.Errors.Add(new UnauthorisedError($"Fail to authorize policy: {policyName}"));
    }
}

But how can I configure different policies for different reroutes?

Thank you

Specifications

  • Version: V3.1.9
  • Platform: win10 x64
@TomPallister
Copy link
Member

@yiluomyt thanks for your interest in the project!! :)

You have access to the ReRoute on the ctx object. ctx.DownstreamReRoute this should give you information that you can use to decide which policy to use.

You would need a mapping between policies and ReRoutes somewhere if you used a dictionary something like this

//somewhere when application starts 
var reRouteToPolicy = new Dictionary<string, string>();
reRouteToPolicy.Add("ReRoute.Key from configuration.json", "policyName");
//below is pseudo code I would recommend putting into ioc
services.Add(reRouteToPolicy);

//then in middleware
var policies = context.HttpContext.RequestServices.GetService<Dictionary<string, string>>();
var policyForReRoute = policies[ctx.DownstreamReRoute.Key];
//use policy

I hope that helps!

@TomPallister TomPallister added the question Initially seen a question could become a new feature or bug or closed ;) label Mar 7, 2018
@yiluomyt
Copy link
Author

yiluomyt commented Mar 8, 2018

It worked! Thanks for your help.

@yiluomyt yiluomyt closed this as completed Mar 8, 2018
@miemengniao
Copy link

Hi ,

how can I configure DownstramReRote.Key?
my json file like below, but I cannot get the key's value in the middleware.
{
"ReRoutes": [
{
.....
"Key": "Laura",
"RequestIdKey": "abcd",
......
}
],

"GlobalConfiguration": {
"RequestIdKey": "Request-Id",
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500
},
"BaseUrl": "http://localhost:5000"
}
}

Best Wishes,
yazheng

@TomPallister
Copy link
Member

@miemengniao what does your middleware look like?

@feugen24
Copy link

downstream key is simply a key for rereoute and it works if it hits a reroute with a key, it took me a while to find it in the docs

@gurutcr
Copy link

gurutcr commented Jul 20, 2020

Expected Behavior / New Feature

I would like to override the AuthorisationMiddleware to use the policy-based authorization.

Actual Behavior / Motivation for New Feautre

According to the document, now I try this way to achieve.

AuthorisationMiddleware = async (ctx, next) =>
{
    // How can I configure the policy name for the ReRoute
    string policyName = "admin";
    IAuthorizationService authorizationService = ctx.HttpContext.RequestServices.GetService<IAuthorizationService>();
    var result = await authorizationService.AuthorizeAsync(ctx.HttpContext.User, policyName);
    if (result.Succeeded)
    {
        await next.Invoke();
    }
    else
    {
        ctx.Errors.Add(new UnauthorisedError($"Fail to authorize policy: {policyName}"));
    }
}

But how can I configure different policies for different reroutes?

Thank you

Specifications

  • Version: V3.1.9
  • Platform: win10 x64

I am new to Ocelot. I have a question. The following is the scenario.

I call an authentication web api from Ocelot using the configuration.json as below.

  "AuthenticationOptions": {
    "AuthenticationProviderKey": "TestKey",
    "AllowedScopes": []
  }

That authentication web api project has the following code

        var claims = new[]
        {
                new Claim(JwtRegisteredClaimNames.Sub,UserFullName),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(), ClaimValueTypes.Integer64),
                new Claim("OfficeUser", "true"),
        };
        var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_settings.Value.Secret));
        var token = new JwtSecurityToken(
            issuer: _settings.Value.Iss,
            audience: _settings.Value.Aud,
            claims: claims,
            notBefore: now,
            expires: now.Add(TimeSpan.FromMinutes(20)),
            signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
        );

        return Ok(new
        {
            token = new JwtSecurityTokenHandler().WriteToken(token),
            expiration = token.ValidTo
        });

In the ocelot API project, I have the following in startup

   public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
        services.AddScoped<IAuthorizationHandler, OfficeAccessHandler>();
        var audienceConfig = Configuration.GetSection("Audience").Get<Audience>();
        var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(audienceConfig.Secret));
        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = signingKey,
            ValidateIssuer = true,
            ValidIssuer = audienceConfig.Iss,
            ValidateAudience = true,
            ValidAudience = audienceConfig.Aud,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero,
            RequireExpirationTime = true,
        };
        services.AddAuthorization(options =>
        {
            options.AddPolicy("ShouleBeOfficeUser", policy =>
                policy.Requirements.Add(new OfficeAccessRequirement(10)));
        });
        services.AddAuthentication(o =>
        {
            o.DefaultAuthenticateScheme = "TestKey";
        })
        .AddJwtBearer("TestKey", x =>
        {
            x.RequireHttpsMetadata = false;
            x.TokenValidationParameters = tokenValidationParameters;
        });
        services.AddOcelot(Configuration);
        services.AddMvc();
    }

   public async void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseStaticFiles();
        app.UseAuthentication();
        var configuration = new OcelotPipelineConfiguration
        {
            AuthorisationMiddleware = async (ctx, next) =>
            {
                string policyName = "ShouldBeOfficeUser";
                IAuthorizationService authorizationService = ctx.HttpContext.RequestServices.GetService<IAuthorizationService>();
                var result = await authorizationService.AuthorizeAsync(ctx.HttpContext.User, policyName);
                if (result.Succeeded)
                {
                    await next.Invoke();
                }
                else
                {
                    ctx.Errors.Add(new UnauthorisedError($"Fail to authorize policy: {policyName}"));
                }
            }
        };
        await app.UseOcelot(configuration);
        app.UseAuthentication();
        //app.UseMvc();
    }

Here is the authorization handler in the ocelot api project

public class OfficeAccessHandler : AuthorizationHandler<OfficeAccessRequirement>
{
    IHttpContextAccessor httpContextAccessor = null;
    public OfficeAccessHandler(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
    }
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OfficeAccessRequirement requirement)
    {
        HttpContext httpContext = httpContextAccessor.HttpContext;

        var isSuperAdmin = bool.Parse(httpContext.User.FindFirst("OfficeUser").Value);

        if (isSuperAdmin == true)
        {
            context.Succeed(requirement);
            return;
        }
        else
        {
            context.Fail();
            return;
        }
    }
}

So basically, during authentication I set the claim "OfficeUser" as "true" and try to use that in the authorizationhandler of ocelot api project to evaluate to success or failure. It is not working. I don't get the claims in the httpContext.User object.

Is my approach here totally wrong? Or is it that I am missing something? Please help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Initially seen a question could become a new feature or bug or closed ;)
Projects
None yet
Development

No branches or pull requests

5 participants