openiddict / openiddict-samples

.NET samples for OpenIddict
https://documentation.openiddict.com/
Apache License 2.0
714 stars 298 forks source link

Mobile Authentication Help Please? #329

Closed jacob925 closed 2 months ago

jacob925 commented 2 months ago

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

Version

5.0

Question

I am trying to get mobile authentication working in my .Net MAUI application. I have regular web auth working great (Thanks for the examples!)

I have created a mobile login page (copied from the default login page) and I think all I need now is the redirect with the bearer tokens. my app is set up to accept redirects from /mobileapp/login

in my MobileLogin.cshtml.cs I have this, `public async Task OnPostAsync(string returnUrl = null) { returnUrl ??= Url.Content("~/mobileapp/login");

ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

if (ModelState.IsValid)
{
    // This doesn't count login failures towards account lockout
    // To enable password failures to trigger account lockout, set lockoutOnFailure: true
    var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
    if (result.Succeeded)
    {
        var user = _signInManager.UserManager.Users.FirstOrDefault(x => x.Email == Input.Email);
        if (user != null)
        {
            //var tokens = await _userManager.GetTokensAsync(user);
        }

        _logger.LogInformation("User logged in.");

        return LocalRedirect(returnUrl);
    }`

and it's getting hit just fine but I believe I need to append a token to the redirect? I am trying to use the WebAuthenticator in MAUI: (https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/communication/authentication?view=net-maui-8.0&tabs=macios#aspnet-core-server-back-end) with your openiddict server.

kevinchalet commented 2 months ago

I have created a mobile login page (copied from the default login page) and I think all I need now is the redirect with the bearer tokens.

If you already something working for web apps, you already have a standard OIDC flow in place. As such, I'd recommend using it instead of trying to create something non-standard as shown in the MAUI docs.

For that, you can construct a URI pointing to your /authorize endpoint with all the standard parameters (client_id, redirect_uri, response_type and ideally code_challenge + code_challenge_method) and use it with MAUI's WebAuthenticator (no need for a separate endpoint).

Alternatively, you can wait for iOS and Android support to land in OpenIddict 5.8 or use the nightly builds. You can see the OpenIddict client and its system integration in action here: https://github.com/openiddict/openiddict-core/tree/dev/sandbox/OpenIddict.Sandbox.Maui.Client

Cheers.

jacob925 commented 2 months ago

well, I am trying the authorize endpoint and it is hitting my server (running locally), but I am getting a blank page. ` var paramDict = BaseAPIClient.BuildParms( "client_id", "jspending_mobile_secure_code" ,"client_secret", "fc3b2eea-3f3d-45cb-8fd5-b1903af667a7" ,"redirect_uri", "https://www.jspending.com/mobileapp/login" ,"response_type", "code"); var loginUrl = BaseAPIClient.ParameterizeUrl("http://192.168.1.9:62288/connect/authorize", paramDict);

            WebAuthenticatorResult authResult = await WebAuthenticator.Default.AuthenticateAsync(
                new Uri(loginUrl),
                new Uri("https://www.jspending.com/mobileapp/login"));

`

and my server side authorize is the same as Velusia.Server. here's my client info: await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "jspending_mobile_secure_code", ConsentType = ConsentTypes.Explicit, DisplayName = "JSpending Mobile Secure Client Auth Code Flow", ClientSecret = "fc3b2eea-3f3d-45cb-8fd5-b1903af667a7", RedirectUris = { new Uri($"https://www.jspending.com/mobileapp/login"), }, Permissions = { Permissions.Endpoints.Authorization, Permissions.Endpoints.Logout, Permissions.Endpoints.Token, Permissions.GrantTypes.AuthorizationCode, Permissions.ResponseTypes.Code, Permissions.Scopes.Email, Permissions.Scopes.Profile, Permissions.Scopes.Roles, Permissions.Prefixes.Scope + "api" }, Requirements = { //Requirements.Features.ProofKeyForCodeExchange } });

and it is definitely getting here: ` var parameters = Request.HasFormContentType ? Request.Form.Where(parameter => parameter.Key != Parameters.Prompt).ToList() : Request.Query.Where(parameter => parameter.Key != Parameters.Prompt).ToList();

       parameters.Add(KeyValuePair.Create(Parameters.Prompt, new StringValues(prompt)));

       // For scenarios where the default challenge handler configured in the ASP.NET Core
       // authentication options shouldn't be used, a specific scheme can be specified here.
       return Challenge(new AuthenticationProperties
       {
           RedirectUri = Request.PathBase + Request.Path + QueryString.Create(parameters)
       });`
kevinchalet commented 2 months ago
  1. You should NEVER send a client secret in an authorization request. In this case, consider declaring your client as a public client (i.e without a client secret).

  2. Anything interesting in the logs?

jacob925 commented 2 months ago

oh. well now. It's trying to go to /account/login instead of identity/account/login OOPS: Remove client secret :)

logs show: OpenIddict.Server.OpenIddictServerDispatcher: Information: The request URI matched a server endpoint: Authorization. OpenIddict.Server.OpenIddictServerDispatcher: Information: The authorization request was successfully extracted: { "client_id": "jspending_mobile_secure_code", "client_secret": "[redacted]", "redirect_uri": "https://www.jspending.com/mobileapp/login", "response_type": "code" }. The thread 50148 has exited with code 0 (0x0). OpenIddict.Server.OpenIddictServerDispatcher: Information: The authorization request was successfully validated.

jacob925 commented 2 months ago

ah ha.... I have generated ALL of the default identity server auth pages, but I still needed to set .AddDefaultUI(); in order for it to know where the login page was. Is there a way to specify the location of the challenge login page?

kevinchalet commented 2 months ago

Is there a way to specify the location of the challenge login page?

You should be able to override the default value using services.ConfigureApplicationCookie(options => options.LoginPath = "/test") 😃

kevinchalet commented 2 months ago

Do you still need help, @jacob925? 😃

jacob925 commented 2 months ago

No sir, I’m sorted out now. Thanks,JacobOn Jul 15, 2024, at 1:04 PM, Kévin Chalet @.***> wrote: Do you still need help, @jacob925? 😃

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>

kevinchalet commented 2 months ago

Great to hear! 👍🏻