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

Document Web Providers #57

Open
1 task done
verdie-g opened this issue Apr 18, 2023 · 3 comments
Open
1 task done

Document Web Providers #57

verdie-g opened this issue Apr 18, 2023 · 3 comments

Comments

@verdie-g
Copy link

verdie-g commented Apr 18, 2023

Confirm you've already contributed to this project or that you sponsor it

  • I confirm I'm a sponsor or a contributor

Describe the solution you'd like

Using web providers such as Github is barely documented. In the Contributing a new Web provider, it quickly mentions how to test it's hard to know what to do just for that. On Github it seems like no projects use the web providers (sourcegraph).

Here are the questions I've asked myself when reading trying to use web providers with open iddict:

  • The AddClient method confused me. I supposed our OIDC server is now a OIDC client too
  • Is the UseSystemNetHttp needed? What happens if I don't specifiy it?
  • Are the certificates used are different than the ones used by the server?
  • Once I registered the Github provider, how can I challenge it? Does automatically use identity_provider?
  • A bit of an edge case but when I also use Steam auth (Open ID 2.0), can I use identity_provider=steam?

Additional context

No response

@kevinchalet kevinchalet transferred this issue from openiddict/openiddict-core Apr 18, 2023
@kevinchalet
Copy link
Member

kevinchalet commented Apr 18, 2023

I moved your ticket to the correct repository 😃

Using web providers such as Github is barely documented. In the Contributing a new Web provider, it quickly mentions how to test it's hard to know what to do just for that.

I wrote a blog post about that here (and it uses GitHub as the provider): https://kevinchalet.com/2022/12/16/getting-started-with-the-openiddict-web-providers/.

I'll use this thread to track adding docs on documentation.openiddict.com.

On Github it seems like no projects use the web providers (sourcegraph).

It's not entirely surprising: the whole new OpenIddict client and the web provider integrations that come with it shipped as part of OpenIddict 4.0, in December 2022, so the usage is still low (and we decided to keep supporting the aspnet-contrib providers, so many folks will likely keep using them).

That said, we're considering using them in OrchardCore in the next version and multiple OpenIddict users I know have adopted them.

The AddClient method confused me. I supposed our OIDC server is now a OIDC client too

Yes: when you integrate with GitHub, your application is now acting as an OAuth 2.0 client. Hence the name, "client" 😃

Is the UseSystemNetHttp needed? What happens if I don't specifiy it?

This method is always called by the UseWebProviders() extension provided by the OpenIddict.Client.WebIntegration, so you don't have to call it. That said, using it is useful to customize the HTTP transport aspects, like setting a custom user agent string as shown here: https://github.com/openiddict/openiddict-samples/blob/cac41209bd9b248b207a53a7c3f40285a81cd1dd/samples/Mimban/Mimban.Server/Program.cs#L56-L60

Are the certificates used are different than the ones used by the server?

Nothing prevents you from reusing the same certificates, but using different ones is recommended. If you use the web providers in a .NET desktop app, read https://kevinchalet.com/2023/02/27/introducing-system-integration-support-for-the-openiddict-client/ for additional considerations.

Once I registered the Github provider, how can I challenge it?

Assuming you're using the GitHub provider in an ASP.NET Core app:

[HttpGet("~/login")]
public ActionResult LogIn(string returnUrl)
{
    var properties = new AuthenticationProperties(new Dictionary<string, string>
    {
        // Note: when only one client is registered in the client options,
        // setting the provider property is not required and can be omitted.
        [OpenIddictClientAspNetCoreConstants.Properties.ProviderName] = Providers.GitHub
    })
    {
        // Only allow local return URLs to prevent open redirect attacks.
        RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : "/"
    };

    // Ask the OpenIddict client middleware to redirect the user agent to the identity provider.
    return Challenge(properties, OpenIddictClientAspNetCoreDefaults.AuthenticationScheme);
}

Does automatically use identity_provider?

Assuming you're referring to the special/custom parameter used in one of the samples, no.

A bit of an edge case but when I also use Steam auth (Open ID 2.0), can I use identity_provider=steam?

Yep, expect the authentication scheme value will need to point to SteamAuthenticationDefaults.AuthenticationScheme instead of OpenIddictClientAspNetCoreDefaults.AuthenticationScheme when triggering a Steam challenge.

Hope it's clearer.

@verdie-g
Copy link
Author

Thanks a lot, each line was a "aaah 🤯". I was able to get my web provider working along with Steam. Though I think I have some inaccuracies.

the authentication scheme value will need to point to SteamAuthenticationDefaults.AuthenticationScheme instead of OpenIddictClientAspNetCoreDefaults.AuthenticationScheme when triggering a Steam challenge

In my authorize endpoint I'm now doing a

  string authenticationScheme = request.IdentityProvider == "Steam"
      ? SteamAuthenticationDefaults.AuthenticationScheme
      : OpenIddictClientAspNetCoreDefaults.AuthenticationScheme;

  return Challenge(
      authenticationSchemes: authenticationScheme,

but at the start of the authorize I'm checking (like in the samples) if an authentication cookie is available using

HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);

but here I'm super confused. Since I set the steam's SignInScheme to CookieAuthenticationDefaults.AuthenticationScheme I guess that makes sense, but I didn't specify that scheme anywhere for OpenIddict. So it's unclear what I'm checking here.

Also, looking at my cookies in the browser, I can only one cookie named .AspNetCore.Cookies. I think I was expecting to see a cookie for Steam and one for OpenIddict. A lot is still magical to me 😅

@kevinchalet
Copy link
Member

but at the start of the authorize I'm checking (like in the samples) if an authentication cookie is available using

HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);

but here I'm super confused. Since I set the steam's SignInScheme to CookieAuthenticationDefaults.AuthenticationScheme I guess that makes sense, but I didn't specify that scheme anywhere for OpenIddict. So it's unclear what I'm checking here.

As mentioned in aspnet-contrib/AspNet.Security.OAuth.Providers#694 (comment), OpenIddict - unlike the Microsoft and aspnet-contrib OAuth 2.0/OIDC handlers - doesn't have a SignInScheme that allows delegating the persistance part to a different authentication handler (typically an instance of the cookie authentication handler).

Instead, you have to implement a /callback action in your code that explicitly calls SignIn(CookieAuthenticationDefaults.AuthenticationScheme) with the identity you want to persist. With the Steam handler, it's done magically for you as part of the internal callback handler.

Also, looking at my cookies in the browser, I can only one cookie named .AspNetCore.Cookies. I think I was expecting to see a cookie for Steam and one for OpenIddict. A lot is still magical to me 😅

Given you use CookieAuthenticationDefaults.AuthenticationScheme as both the SignInScheme for Steam and the scheme in your OpenIddict /callback action, the two things end up sharing the same cookie. If you want to have separate cookies, use separate instances of the cookie authentication handler with different scheme and cookie names 😃

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

No branches or pull requests

2 participants