0

I'm trying to use two separate OpenIDConnect auth options in my ASP.NET Framework app. In my IdentitySetup I register two Auth methods:

app.UseOpenIdConnectAuthentication(new AuthOptionsOne());
app.UseOpenIdConnectAuthentication(new AuthOptionsTwo());

Where both of these inherit from OpenIdConnectAuthenticationOptions. they then insert a unique name into the base constructor:

public AuthOptionsOne() : base("AuthOne") ...
public AuthOptionsTwo() : base("AuthTwo") ...

Then, on my constructors I'm using a CustomAttribute on my controller methods:

public class CustomAuthorize: AuthorizeAttribute { private readonly string _authenticationType;

    public CustomAuthorize(string authenticationType = "AuthOne")
    {
        _authenticationType = authenticationType;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var owinContext = filterContext.HttpContext.GetOwinContext();
        var authentication = owinContext.Authentication;

        var identity =
            authentication.User.Identities.FirstOrDefault(i => i.AuthenticationType == _authenticationType);
        
        if (identity is null || !identity.IsAuthenticated)
        {
            authentication.Challenge(_authenticationType);
        }

        base.OnAuthorization(filterContext);
    }
}

My assumption here was that the authenticationtype in the identity was the same as the one in the options - It now appears it is not. The default Identity I can't use, as if I authenticate one, the other would be allowed.

My question is pretty much, how can I go about conditionally authenticating via one of these authentication types or the other?

1
  • but if you want to use "Cookies" as authentication type, how can i challenge a specific provider?
    – Dan Deneau
    Dec 9, 2023 at 0:14

1 Answer 1

1

The challenge you're facing is the differentiation between the AuthenticationType in the OpenIdConnectAuthenticationOptions and the AuthenticationType in the ClaimsIdentity post successful authentication.

Solutions:

  1. Unique ClaimsIssuer:

    • Distinguish between the two OpenID providers using the ClaimsIssuer property of the ClaimsIdentity.
    • Set a unique ClaimsIssuer for each OpenIdConnectAuthenticationOptions:
    public AuthOptionsOne() : base("AuthOne")
    {
        TokenValidationParameters = new TokenValidationParameters
        {
            ValidIssuer = "UniqueIssuerForAuthOne",
        };
    }
    
    public AuthOptionsTwo() : base("AuthTwo")
    {
        TokenValidationParameters = new TokenValidationParameters
        {
            ValidIssuer = "UniqueIssuerForAuthTwo",
        };
    }
    
    • In your CustomAuthorize attribute, you can then inspect the ClaimsIssuer of the ClaimsIdentity:
    var identity = authentication.User.Identities.FirstOrDefault(i => i.ClaimsIssuer == _authenticationType);
    
  2. Authentication Response Received:

    • Set a claim during the AuthenticationResponseReceived notification:
    public AuthOptionsOne() : base("AuthOne")
    {
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthenticationResponseReceived = context =>
            {
                context.AuthenticationTicket.Identity.AddClaim(new Claim("provider", "AuthOne"));
                return Task.FromResult(0);
            }
        };
    }
    
    public AuthOptionsTwo() : base("AuthTwo")
    {
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthenticationResponseReceived = context =>
            {
                context.AuthenticationTicket.Identity.AddClaim(new Claim("provider", "AuthTwo"));
                return Task.FromResult(0);
            }
        };
    }
    
    • In your CustomAuthorize attribute, inspect this custom claim:
    var identity = authentication.User.Identities.FirstOrDefault(i => i.HasClaim("provider", _authenticationType));
    
  3. Custom Middleware:

    • If the above solutions don't provide the flexibility you need, consider crafting a custom OWIN middleware. This middleware can intercept the authentication process and alter the ClaimsIdentity as deemed necessary.

In summary, the essence is ensuring you can effectively distinguish between the two authentication providers, thereby challenging the suitable one when needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.