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

Protected Resource Builder + MVC #104

Open
NikiforovAll opened this issue May 12, 2024 · 6 comments
Open

Protected Resource Builder + MVC #104

NikiforovAll opened this issue May 12, 2024 · 6 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@NikiforovAll
Copy link
Owner

No description provided.

@NikiforovAll NikiforovAll added the bug Something isn't working label May 12, 2024
@NikiforovAll
Copy link
Owner Author

Currently, header propagation middleware assumes the presence of an access token in a header. This is not true for cookie-based applications

@luylucas10
Copy link

Is there a way, even not official from the library, to do that? I'm building a mvc app and I really want to use this keycloak resource. I've tryied on some ways, but didn't work.

I used the source directly, trying to put the tokens on cookies and recover, but no success.

@NikiforovAll
Copy link
Owner Author

Hi @luylucas10 , it should be possible. The only issue is to find a valid token for exchange. Have you tried exchaing id_token?

@luylucas10
Copy link

luylucas10 commented Jul 16, 2024

EDIT: Nop, It doesn't work, I've tested more now and have a problem to check permission because ideed it needs the user token, not just api access.

I could find a way.

I put "DisableHeaderPropagation": true in the keycloak section in appsettings.cs, configuring the Program.cs like this:

builder
    .Services
    .AddAuthorization()
    .AddKeycloakAuthorization()
    .AddAuthorizationServer(builder.Configuration)
    .ConfigureHttpClient(async (provider, client) =>
    {
        var tokenResponse = await client.RequestTokenAsync(new TokenRequest()
        {
            Address = builder.Configuration["Keycloak:auth-server-url"]+ "realms/" + builder.Configuration["Keycloak:realm"] + "/protocol/openid-connect/token",
            GrantType = "client_credentials",
            ClientId = builder.Configuration["Keycloak:resource"],
            ClientSecret = builder.Configuration["Keycloak:credentials:secret"],
        });
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenResponse.TokenType, tokenResponse.AccessToken);
    });

// Add services to the container.
builder.Services.AddControllersWithViews(a => a.AddProtectedResources());

I think that isn't the best way, but works. I'd try to use Duende Token Management but had problems with DI. Now in the action I can use [ProtectedResource("resource", "scope")] in the MVC controllers.

If you could provide a better solution I'll really appreciate that. I can commit this example, I've created a new project at samples directory of the repo.---

@luylucas10
Copy link

Finally I have a solution.

This was the reference that I used: https://github.com/mderriey/aspnet-core-token-renewal/blob/master/src/MvcClient/Startup.cs

We still need the "DisableHeaderPropagation": true in the appsettings and our program.cs like this:

builder
    .Services
    .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddKeycloakWebApp(builder.Configuration.GetSection(KeycloakAuthenticationOptions.Section),
        configureOpenIdConnectOptions: options =>
        {
            options.SaveTokens = true;
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.GetClaimsFromUserInfoEndpoint = true;
            options.MapInboundClaims = false;
            options.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
            options.TokenValidationParameters.RoleClaimType = ClaimTypes.Role;
            options.Events = new OpenIdConnectEvents
            {
                OnSignedOutCallbackRedirect = context =>
                {
                    context.Response.Redirect("/");
                    context.HandleResponse();
                    return Task.CompletedTask;
                },
                // guess this is the needed configurationn
                OnTokenResponseReceived = context =>
                {
                    var identity = context?.Principal?.Identity as ClaimsIdentity;
                    identity?.AddClaims(new[]
                    {
                        new Claim("access_token", context.TokenEndpointResponse.AccessToken),
                        new Claim("id_token", context.TokenEndpointResponse.IdToken)
                    });
                   // makes cookie and token with same expiration
                    context.Properties.IsPersistent = true;
                    context.Properties.ExpiresUtc = new JwtSecurityToken(context.TokenEndpointResponse.AccessToken).ValidTo;
                    return Task.CompletedTask;
                }
            };
        });

builder
    .Services
    .AddAuthorization()
    .AddKeycloakAuthorization()
    .AddAuthorizationServer(builder.Configuration)
    .ConfigureHttpClient(async (provider, client) =>
    {
        // get the token from user cookie and put in the header
        var ctx = provider?.GetService<IHttpContextAccessor>()?.HttpContext;
        var header = new AuthenticationHeaderValue("Bearer", await ctx?.GetTokenAsync("access_token"));
        client.DefaultRequestHeaders.Authorization = header;
    });

Now I have the [ProtectedResource] working. Thank you for working on this integration for dotnet, I'll contribute, but for now, I have to speed up my personal project.

@NikiforovAll
Copy link
Owner Author

Awesome, I'm looking forward to your contribution. Looks good to me!

@NikiforovAll NikiforovAll added the help wanted Extra attention is needed label Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants