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

[API Proposal]: SignOut overloads that take only one authentication scheme #49391

Closed
ghost opened this issue Jul 13, 2023 · 6 comments
Closed
Labels
area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer enhancement This issue represents an ask for new feature or an enhancement to an existing one

Comments

@ghost
Copy link

ghost commented Jul 13, 2023

Background and Motivation

When multiple authentication schemes are registered, if we only want to sign out from a particular one it is necessary to allocate a collection. It is not the most efficient in terms of allocation.

public static IResult SignOut(AuthenticationProperties? properties = null, IList<string>? authenticationSchemes = null)

public static SignOutHttpResult SignOut(AuthenticationProperties? properties = null, IList<string>? authenticationSchemes = null)

public virtual SignOutResult SignOut(params string[] authenticationSchemes)

Proposed API

Add overloads that take a single authentication scheme.

namespace Microsoft.AspNetCore.Http;

public static partial class Results
{
+    public static IResult SignOut(AuthenticationProperties? properties = null, string? authenticationScheme = null)
}

public static partial class TypedResults
{
+    public static SignOutHttpResult SignOut(AuthenticationProperties? properties = null, string? authenticationScheme = null)
}
namespace Microsoft.AspNetCore.Mvc;

public abstract partial class ControllerBase
{
+    public virtual SignOutResult SignOut(string authenticationScheme)
}

Usage Examples

app.MapGet("/signout", () =>
{
    return TypedResults.SignOut(authenticationScheme: "Cookies");
});

Risks

Nothing I can see now

@ghost ghost added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Jul 13, 2023
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer label Jul 13, 2023
@Tratcher
Copy link
Member

Another:

public SignOutResult(string authenticationScheme)
: this(new[] { authenticationScheme })

@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Jul 19, 2023
@mkArtakMSFT mkArtakMSFT added this to the Backlog milestone Jul 19, 2023
@Tratcher Tratcher added api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation labels Oct 27, 2023
@ghost
Copy link

ghost commented Oct 27, 2023

Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:

  • The PR contains changes to the reference-assembly that describe the API change. Or, you have included a snippet of reference-assembly-style code that illustrates the API change.
  • The PR describes the impact to users, both positive (useful new APIs) and negative (breaking changes).
  • Someone is assigned to "champion" this change in the meeting, and they understand the impact and design of the change.

@halter73
Copy link
Member

halter73 commented Dec 7, 2023

public static partial class TypedResults
{
+    public static SignOutHttpResult SignOut(AuthenticationProperties? properties = null, string? authenticationScheme = null)
}

We have to be careful with default values. We do not to make TypedResults.SignOut() ambiguous between this and SignOut(AuthenticationProperties? properties = null, IList<string>? authenticationSchemes = null). I would say we could just remove the default values from the existing overload to maintain both source and binary compatibility as recommended in the rosly docs for adding optional parameters in public API, but that doesn't work when the new overload takes a different type string? instead of IList<string>? in the same position.

We'll probably just have to leave out the default values. Which makes me wonder, if we should add just TypedResults.SignOut(params string[] authenticationScheme) similar to ControllerBase.SignOut()

namespace Microsoft.AspNetCore.Mvc;

public abstract partial class ControllerBase
{
+    public virtual SignOutResult SignOut(string authenticationScheme)
}

What's the motivation for this considering the params overload exists? Just to save an array allocation?

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@wtgodbe wtgodbe removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@halter73 halter73 modified the milestones: Backlog, .NET 9 Planning Feb 9, 2024
@wtgodbe wtgodbe removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 13, 2024
@dotnet dotnet deleted a comment from dotnet-policy-service bot Feb 13, 2024
@dotnet dotnet deleted a comment from dotnet-policy-service bot Feb 13, 2024
@halter73
Copy link
Member

halter73 commented Feb 29, 2024

API Review Notes:

  • We think that the updated code does look nicer than having to allocate an array:
     app.MapGet("/signout", () =>
     {
         return TypedResults.SignOut(authenticationScheme: "Cookies");
     });
    vs.
     app.MapGet("/signout", () =>
     {
         return TypedResults.SignOut(authenticationSchemes: new[] { "Cookies" });
     });
  • The API as proposed is a breaking change as noted in my earlier comment, so we cannot accept it as-is.
  • We might consider an API proposal that adds TypedResults.SignOut(params string[] authenticationScheme) similar to ControllerBase.SignOut(), but that does not remove the array allocation.

We tried to come up with an API proposal that would be non breaking. Below is as far as we got, but even this would probably break given a call like TypedResults.SignOut(authenticationSchemes: new List<string> { "Cookies" }) as soon as we add a params string[] authenticationSchemes overload.

namespace Microsoft.AspNetCore.Http;

public static partial class Results
{
+    public static IResult SignOut()
-    public static IResult SignOut(AuthenticationProperties? properties = null, IList<string>? authenticationSchemes = null)
+   public static IResult SignOut(AuthenticationProperties? properties, IList<string>? authenticationSchemes = null)
+    public static IResult SignOut(params string[] authenticationSchemes)
}

public static partial class TypedResults
{
+    public static SignOutHttpResult SignOut()
-     public static SignOutHttpResult SignOut(AuthenticationProperties? properties = null, IList<string>? authenticationSchemes = null)
+    public static SignOutHttpResult SignOut(AuthenticationProperties? properties, IList<string>? authenticationSchemes = null)
+    public static SignOutHttpResult SignOut(params string[] authenticationSchemes)
}

Because of the difficulty in maintaining backward compatibility, we've decided to reject the API.

@halter73 halter73 removed the api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews label Feb 29, 2024
@martincostello
Copy link
Member

I guess C# 12 at least makes it slightly less ugly (and then maybe the compiler can optimise it?):

app.MapGet("/signout", () =>
 {
     return TypedResults.SignOut(authenticationScheme: ["Cookies"]);
 });

@halter73
Copy link
Member

I agree it looks a bit better with the C# 12 syntax.

The final iteration at our attempt at a non-breaking change might work if we renamed params string[] authenticationSchemes to something like params string[] authenticationSchemeParams, and I'm sympathetic to wanting TypedResults.SignOut("Cookies") to just work, but I'm not sure it's worth it if we have to add a bunch of new overloads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer enhancement This issue represents an ask for new feature or an enhancement to an existing one
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
@halter73 @martincostello @Tratcher @wtgodbe @mkArtakMSFT and others