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

Unable to access proper values for CookieAuthenticationOptions #17631

Open
hishamco opened this issue Mar 16, 2025 · 10 comments
Open

Unable to access proper values for CookieAuthenticationOptions #17631

hishamco opened this issue Mar 16, 2025 · 10 comments
Assignees
Labels

Comments

@hishamco
Copy link
Member

Describe the bug

While I'm working on OrchardCoreContrib.ContentPermissions I noticed that calling IOptions<CookieAuthenticationOptions> from DI gets default values, not the one that are set by OC

Orchard Core version

Latest bits

To Reproduce

Try to get the IOptions<CookieAuthenticationOptions> from any Controller, View, or Razor Page

Expected behavior

It should return the values that are overridden by the OC.Users module`

Logs and screenshots

None

@kevinchalet
Copy link
Member

kevinchalet commented Mar 16, 2025

While I'm working on OrchardCoreContrib.ContentPermissions I noticed that calling IOptions<CookieAuthenticationOptions> from DI gets default values, not the one that are set by OC

The ASP.NET Core authentication handlers use named options (matching what's called the "authentication scheme"), so the fact you're getting a "blank" instance when using IOptions<CookieAuthenticationOptions> is actually expected, since nothing by default uses the default options name in the authentication stack.

Instead, use IOptionsManager<CookieAuthenticationOptions> and call .Get(IdentityConstants.ApplicationCookie) to get the options used for the application cookie, which is where the login path is set.

@hishamco
Copy link
Member Author

you're getting a "blank" instance when using IOptions

I get the default values, for example, Account/AccessDenied for AccessDeniedPath

Instead, use IOptionsManager and call .Get(IdentityConstants.ApplicationCookie) to get the options used for the application cookie, which is where the login path is set.

Let me check

@kevinchalet
Copy link
Member

kevinchalet commented Mar 16, 2025

Or better, return a proper challenge, e.g by calling response.ChallengeAsync() with the IdentityConstants.ApplicationCookie scheme 😃
In that case, the 302 redirection to the login page will be performed by the cookie handler itself.

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.authenticationhttpcontextextensions.challengeasync?view=aspnetcore-8.0#microsoft-aspnetcore-authentication-authenticationhttpcontextextensions-challengeasync(microsoft-aspnetcore-http-httpcontext-system-string)

@hishamco
Copy link
Member Author

hishamco commented Mar 16, 2025

Do you mean IOptionsMonitor<CookieAuthenticationOptions>?

Also IdentityConstants.ApplicationScheme

@kevinchalet
Copy link
Member

Yeah and yeah (never reply when on your smartphone 🤣)

@hishamco
Copy link
Member Author

Thanks, it works :)

Could you please let me know why this causes an issue while ConfigureSecurityStampOptions doesn't?

@kevinchalet
Copy link
Member

You mean ConfigureApplicationCookie? 😄

That's because it's name-aware and only amends the options attached to the IdentityConstants.ApplicationScheme cookie instance: https://github.com/dotnet/aspnetcore/blob/825daf664804598df9942499970bee5e0f2432d5/src/Identity/Core/src/IdentityServiceCollectionExtensions.cs#L160-L161

Essentially, it does something like this:

public void PostConfigure(string name, CookieAuthenticationOptions options)
{
    if (name is not IdentityConstants.ApplicationScheme)
        return;

    // Only amend the options if the options name matches the application scheme (main cookie instance used by Identity).
}

@hishamco
Copy link
Member Author

You mean ConfigureApplicationCookie? 😄

I mean ConfigureSecurityStampOptions :)

@kevinchalet
Copy link
Member

The SecurityStampOptions options are not named, so there's only one instance ever used by ASP.NET Core Identity: https://github.com/dotnet/aspnetcore/blob/3ed4a7b46f736255ef830b86b28b220dea0ce88e/src/Identity/Core/src/SecurityStampValidator.cs#L44-L49

But even if they were not named, it wouldn't be problematic anyway as ConfigureSecurityStampOptions only sets a delegate hook:

public class ConfigureSecurityStampOptions : IPostConfigureOptions<SecurityStampValidatorOptions>
{
public void PostConfigure(string name, SecurityStampValidatorOptions options)
{
// While updating the principal, any customized claims set using IUserClaimsProvider
// or obtained from an external identity will persist and transfer to the refreshed/new principal.
options.OnRefreshingPrincipal = principalContext =>
{
var currentIdentity = principalContext.CurrentPrincipal?.Identities?.FirstOrDefault();
if (currentIdentity is not null && principalContext.NewPrincipal.Identities is not null)
{
var newIdentity = principalContext.NewPrincipal.Identities.First();
foreach (var claim in currentIdentity.Claims)
{
if (newIdentity.HasClaim(claim.Type, claim.Value))
{
continue;
}
newIdentity.AddClaim(new Claim(claim.Type, claim.Value));
}
}
return Task.CompletedTask;
};
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants