question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Getting Openiddict server working with credentials and authorization flow

See original GitHub issue

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

  • I confirm I’m a sponsor or a contributor

Version

4.x

Question

I have this repo for my server. It is setup to do credential and authorization code flows. I have gone through the examples and used code from there and two articles on creating and openiddict authorization server. The code right now does not verify the user, I am looking to get the code flows working for the two clients.

There are client apps for testing that use OpenIddict Client.

The server setup, authorization and account controllers are shown below. I have a client credentials app that fails with a protocol exception, and an authorization code client app. The authorization setup and token access code are shown below. Authorization fails with Content-Type not set. Any help you could provide would be appreciated.

OpenIddict.Server.OpenIddictServerDispatcher: Information: The request URI matched a server endpoint: Authorization. OpenIddict.Server.OpenIddictServerDispatcher: Information: The request was rejected because the mandatory ‘Content-Type’ header was missing. OpenIddict.Server.OpenIddictServerDispatcher: Information: The response was successfully returned as a plain-text document: { “error”: “invalid_request”, “error_description”: “The mandatory ‘Content-Type’ header is missing.”, “error_uri”: “https://documentation.openiddict.com/errors/ID2081” }.

Authorization Token Access Code

`public class InteractiveService : BackgroundService { private readonly IHostApplicationLifetime _lifetime; private readonly OpenIddictClientService _service;

public InteractiveService(
    IHostApplicationLifetime lifetime,
    OpenIddictClientService service)
{
    _lifetime = lifetime;
    _service = service;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    // Wait for the host to confirm that the application has started.
    var source = new TaskCompletionSource<bool>();
    using (_lifetime.ApplicationStarted.Register(static state => ((TaskCompletionSource<bool>) state!).SetResult(true), source))
    {
        await source.Task;
    }

    Console.WriteLine("Press any key to start the authentication process.");
    await Task.Run(Console.ReadKey).WaitAsync(stoppingToken);

    string token = null;
    try
    {
        // Ask OpenIddict to initiate the authentication flow (typically, by
        // starting the system browser) and wait for the user to complete it.
        var (_, response, _) = await _service.AuthenticateInteractivelyAsync (
            provider: "Local",
            cancellationToken: stoppingToken );

        token = response.AccessToken;


        //Console.WriteLine("Response from Api1: {0}", await GetResourceFromApi1Async(response.AccessToken, stoppingToken));
        //Console.WriteLine("Response from Api2: {0}", await GetResourceFromApi2Async(response.AccessToken, stoppingToken));
    }

    catch (OperationCanceledException)
    {
        Console.WriteLine("The authentication process was aborted.");
    }

    catch (ProtocolException exception) when (exception.Error is Errors.AccessDenied)
    {
        Console.WriteLine("The authorization was denied by the end user.");
    }

    catch
    {
        Console.WriteLine("An error occurred while trying to authenticate the user.");
    }

}

`

Authorization Client Setup Code

` var dbPath = Path.GetDirectoryName ( Assembly.GetExecutingAssembly ().Location );

        var host = new HostBuilder ()

            //.ConfigureLogging(options => options.AddDebug())
            .ConfigureServices ( services =>
            {
                services.AddDbContext<DbContext> ( options =>
                {
                    options.UseSqlite ( $"Filename={Path.Combine ( dbPath, "clientapp.db3" )}" );
                    options.UseOpenIddict ();
                } );


                services.AddOpenIddict ()

                    // Register the OpenIddict Core. components.
                    .AddCore ( options =>
                    {
                        // Configure OpenIddict to use the Entity Framework Core. stores and models.
                        // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities.
                        options.UseEntityFrameworkCore ()
                               .UseDbContext<DbContext> ();
                    } )

                    // Register the OpenIddict client components.
                    .AddClient ( options =>
                    {
                        // Note: this sample uses the authorization code flow,
                        // but you can enable the other flows if necessary.
                        options.AllowAuthorizationCodeFlow ()
                               .AllowRefreshTokenFlow ();

                        // Register the signing and encryption credentials used to protect
                        // sensitive data like the state tokens produced by OpenIddict.
                        options.AddDevelopmentEncryptionCertificate ()
                               .AddDevelopmentSigningCertificate ();

                        // Add the operating system integration.
                        options.UseSystemIntegration ()
                               .SetAllowedEmbeddedWebServerPorts ( 7000 );

                        // Register the System.Net.Http integration and use the identity of the current
                        // assembly as a more specific user agent, which can be useful when dealing with
                        // providers that use the user agent as a way to throttle requests (e.g Reddit).
                        options.UseSystemNetHttp ()
                               .SetProductInformation ( typeof ( Program ).Assembly );

                        // Add a client registration matching the client application definition in the server project.
                        options.AddRegistration ( new OpenIddictClientRegistration
                        {
                            Issuer = new Uri ( "https://localhost:7296/", UriKind.Absolute ),
                            ProviderName = "Local",

                            ClientId = "core_api_client",
							ClientSecret = "859B282C-B62D-44C5-82F4-8B06F16A20E7",
                            
							RedirectUri = new Uri ( "http://localhost:7000/", UriKind.Absolute ),
                            Scopes = { Scopes.OpenId, "gtapi" }
                        } );
                    } );

                //services.AddHttpClient ();

                //services.AddControllersWithViews ();

                // Register the worker responsible for creating the database used to store tokens
                // and adding the registry entries required to register the custom URI scheme.
                //
                // Note: in a real world application, this step should be part of a setup script.
                services.AddHostedService<Worker> ();

                // Register the background service responsible for handling the console interactions.
                services.AddHostedService<InteractiveService> ();

            } )
            .UseConsoleLifetime ()
            .Build ();

        await host.RunAsync ();

`

Client Credentials Code

` internal class Program { static ServiceCollection Services { get; set; }

    static void Main ( string [] args )
    {
        var services = new ServiceCollection ();


        Services = services;

        services.AddOpenIddict ()

            // Register the OpenIddict client components.
            .AddClient ( options =>
            {
                // Allow grant_type=client_credentials to be negotiated.
                options.AllowClientCredentialsFlow ();

                // Disable token storage, which is not necessary for non-interactive flows like
                // grant_type=password, grant_type=client_credentials or grant_type=refresh_token.
                options.DisableTokenStorage ();

                // Register the System.Net.Http integration and use the identity of the current
                // assembly as a more specific user agent, which can be useful when dealing with
                // providers that use the user agent as a way to throttle requests (e.g Reddit).
                options.UseSystemNetHttp ()
                       .SetProductInformation ( typeof ( Program ).Assembly );

                // Add a client registration matching the client application definition in the server project.
                options.AddRegistration ( new OpenIddictClientRegistration
                {
                    Issuer = new Uri ( "https://localhost:7296/", UriKind.Absolute ),

                    ClientId = "core_api_console",
                    ClientSecret = "E2B00F84-82D2-4D43-B081-B4B88283175A",
                } );

            } );

        Run ();
    }

    

    static async void Run ()
    {
        try
        {
            await using var provider = Services.BuildServiceProvider ();

            var token = GetTokenAsync ( provider );


            Console.WriteLine ( "Access token: {0}", token );
            Console.WriteLine ();

            var resource = await GetResourceAsync ( provider, token );
            Console.WriteLine ( "API response: {0}", resource );
            Console.ReadLine ();
        }
        catch ( Exception ex ) 
        {
            Console.WriteLine ( ex.Message );
        }
    }

    //The redirection endpoint must be enabled to use the authorization code and implicit flows

    static string GetTokenAsync ( IServiceProvider provider )
    {
        var service = provider.GetRequiredService<OpenIddictClientService> ();

        var (response, _) = 
            service.AuthenticateWithClientCredentialsAsync ( new Uri ( "https://localhost:7296/", UriKind.Absolute ) ).GetAwaiter ().GetResult ();


        return response.AccessToken;
    }

    static async Task<string> GetResourceAsync ( IServiceProvider provider, string token )
    {
        using var client = provider.GetRequiredService<HttpClient> ();
        using var request = new HttpRequestMessage ( HttpMethod.Get, "https://localhost:7296/api/message" );
        request.Headers.Authorization = new AuthenticationHeaderValue ( "Bearer", token );

        using var response = await client.SendAsync ( request );
        response.EnsureSuccessStatusCode ();

        return await response.Content.ReadAsStringAsync ();
    }
}

`

Server Setup Code

` var builder = WebApplication.CreateBuilder ( args );

        // Add services to the container
        var formAssembly = typeof ( Core.IDP.Forms.Pages.Login ).Assembly;


        // Add services to the container
        builder.Services.AddControllersWithViews ().
            AddApplicationPart ( formAssembly );



        builder.Services.AddDbContext<AppDbContext> ( options =>
        {

            options.UseSqlite ( ConnectionString );

            // Register the entity sets needed by OpenIddict.
            options.UseOpenIddict ();
        } );



        builder.Services.AddOpenIddict ()

            // Register the OpenIddict Core. components
            .AddCore ( options =>
            {
                // Configure OpenIddict to use the EF Core. stores/models
                options.UseEntityFrameworkCore ()
                    .UseDbContext<AppDbContext> ();
            } )

            // Register the OpenIddict server components
            .AddServer ( options =>
            {
                options
                    .AllowAuthorizationCodeFlow ()
                    //.RequireProofKeyForCodeExchange ()
                    .AllowPasswordFlow ()
                    .AllowRefreshTokenFlow ()
                    .AllowClientCredentialsFlow ();

                options
                    .SetAuthorizationEndpointUris ( "/connect/authorize" )
                    .SetTokenEndpointUris ( "/connect/token" )
                    .SetUserinfoEndpointUris ( "/connect/userinfo" );

                // Encryption and signing of tokens
                options
                    .AddEphemeralEncryptionKey ()
                    .AddEphemeralSigningKey ()
                    .DisableAccessTokenEncryption ();

                // Register scopes (permissions)
                options.RegisterScopes ( "gtapi" );

                // Register the ASP.NET Core. host and configure the ASP.NET Core.-specific options
                options
                    .UseAspNetCore ()
                    .EnableTokenEndpointPassthrough ()
                    .EnableAuthorizationEndpointPassthrough ()
                    .EnableUserinfoEndpointPassthrough ();
            } )

        // Register the OpenIddict validation components
        .AddValidation ( options =>
        {
            // Import the configuration from the local OpenIddict server instance
            options.UseLocalServer ();

            // Register the ASP.NET Core. host
            options.UseAspNetCore ();
        } );
        builder.Services.AddAuthorization ();

        builder.Services.AddAuthentication ( CookieAuthenticationDefaults.AuthenticationScheme )
            .AddCookie ( CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.LoginPath = "/login";
            } );

        /*
        .AddAuthentication ( options =>
        {
            options.DefaultAuthenticateScheme = OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCore.Defaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;

        } )
            .AddCookie ();
        */
        ;



        builder.Services.AddHttpClient ();

        builder.Services.AddScoped (
            s =>
            {
                // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
                var navigationManager = s.GetRequiredService<NavigationManager> ();

                return new HttpClient
                {
                    BaseAddress = new Uri ( navigationManager.BaseUri )
                };
            } );


        builder.Services.AddScoped (
            s =>
            {
                var navigationManager = s.GetRequiredService<NavigationManager> ();

                return navigationManager;
            } );


        builder.Services.AddServerSideBlazor ( config => config.DetailedErrors = true );

        builder.Services.AddBlazoredLocalStorage ( config =>
        {
            config.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
            config.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
            config.JsonSerializerOptions.IgnoreReadOnlyProperties = true;
            config.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
            config.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            config.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
            config.JsonSerializerOptions.WriteIndented = true;
        } );

        var sharedAssembly = typeof ( UserState ).Assembly;

        builder.Services.AddFluxor ( options =>
        {

            options.ScanAssemblies (
                Assembly.GetExecutingAssembly (),
                sharedAssembly );

            options.UseReduxDevTools ();
        } );




        builder.Services.AddRazorPages ();
        builder.Services.AddServerSideBlazor ();

        var app = builder.Build ();

        // Configure the HTTP request pipeline.
        if ( !app.Environment.IsDevelopment () )
        {
            app.UseExceptionHandler ( "/Error" );
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetCore.-hsts.
            app.UseHsts ();
        }



        app.UseHttpsRedirection ();

        app.UseStaticFiles ();

        app.UseRouting ();

        app.UseHttpsRedirection ();
        app.UseStaticFiles ();

        app.UseAuthentication ();
        app.UseAuthorization ();

        // Create new application registrations matching the values configured in Zirku.Client and Zirku.Api1.
        // Note: in a real world application, this step should be part of a setup script.
        using ( var scope = app.Services.CreateAsyncScope () )
        {
            var context = scope.ServiceProvider.GetRequiredService<AppDbContext> ();
            context.Database.Migrate ();

            CreateApplicationsAsync ().GetAwaiter ().GetResult ();
            CreateScopesAsync ().GetAwaiter ().GetResult ();

            async Task CreateApplicationsAsync ()
            {

                var manager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager> ();

                if ( await manager.FindByClientIdAsync ( "core_api_client" ) is null )
                {
                    await manager.CreateAsync ( new OpenIddictApplicationDescriptor
                    {
                        ClientId = "core_api_client",
                        ClientSecret = "859B282C-B62D-44C5-82F4-8B06F16A20E7",
                        ConsentType = ConsentTypes.Implicit,

                        RedirectUris =
                        {
                            new Uri("http://localhost:7000/")
                        },
                        Permissions =
                        {
                            Permissions.Endpoints.Authorization,
                            Permissions.Endpoints.Token,
                            Permissions.GrantTypes.AuthorizationCode,
                            Permissions.ResponseTypes.Code,
                            Permissions.Prefixes.Scope + "gtapi",
                        }


                        /*
                        Requirements =
                        {
                            Requirements.Features.ProofKeyForCodeExchange
                        }
                        */
                    } );
                }


                if ( await manager.FindByClientIdAsync ( "core_api_console" ) is null )
                {
                    await manager.CreateAsync ( new OpenIddictApplicationDescriptor
                    {
                        ClientId = "core_api_console",
                        ClientSecret = "E2B00F84-82D2-4D43-B081-B4B88283175A",
                        DisplayName = "My client application",
                        Permissions =
                        {
                            Permissions.Endpoints.Token,
                            Permissions.GrantTypes.ClientCredentials
                        }
                    } );
                }
            }

            async Task CreateScopesAsync ()
            {
                var manager = scope.ServiceProvider.GetRequiredService<IOpenIddictScopeManager> ();

                if ( await manager.FindByNameAsync ( "gtapi" ) is null )
                {
                    await manager.CreateAsync ( new OpenIddictScopeDescriptor
                    {
                        Name = "gtapi",
                        Resources =
                        {
                        "resource_server_1"
                    }
                    } );
                }

            }


        }


        app.MapRazorPages ();
        app.MapControllers ();
        app.MapBlazorHub ();
        app.MapFallbackToPage ( "/_Host" );




        app.Run ();

` Authorization Controller

` public class AuthorizationController : Controller { [Inject] private UserManager UserManager { get; set; }

    [Inject]
    private IOpenIddictApplicationManager ApplicationManager
    { get; set; }

    [Inject]
    private IOpenIddictAuthorizationManager AuthorizationManager
    { get; set; }

    [Inject]
    private IOpenIddictScopeManager ScopeManager
    { get; set; }








    [HttpGet ( "~/connect/authorize" )]
    [HttpPost ( "~/connect/authorize" )]
    [IgnoreAntiforgeryToken]
    public async Task<IActionResult> Authorize ( string redirect_uri = null )
    {
        //ClaimsPrincipal claimsPrincipal = null;

        try
        {

            var request = HttpContext.GetOpenIddictServerRequest () ??
                throw new InvalidOperationException ( "The OpenID Connect request cannot be retrieved." );

            // Try to retrieve the user principal stored in the authentication cookie and redirect
            // the user agent to the login page (or to an external provider) in the following cases:
            //
            //  - If the user principal can't be extracted or the cookie is too old.
            //  - If prompt=login was specified by the client application.
            //  - If a max_age parameter was provided and the authentication cookie is not considered "fresh" enough.
            var result = await HttpContext.AuthenticateAsync ( CookieAuthenticationDefaults.AuthenticationScheme );

            if ( result == null || !result.Succeeded || request.HasPrompt ( Prompts.Login ) ||
               ( request.MaxAge != null && result.Properties?.IssuedUtc != null &&
                DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds ( request.MaxAge.Value ) ) )
            {
                // If the client application requested promptless authentication,
                // return an error indicating that the user is not logged in.
                if ( request.HasPrompt ( Prompts.None ) )
                {
                    return Forbid (
                        authenticationSchemes: CookieAuthenticationDefaults.AuthenticationScheme,
                        properties: new AuthenticationProperties ( new Dictionary<string, string>
                        {
                            [ OpenIddictServerAspNetCoreConstants.Properties.Error ] = Errors.LoginRequired,
                            [ OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription ] = "The user is not logged in."
                        } ) );
                }

                // To avoid endless login -> authorization redirects, the prompt=login flag
                // is removed from the authorization request payload before redirecting the user.
                var prompt = string.Join ( " ", request.GetPrompts ().Remove ( Prompts.Login ) );

                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 ) ) );

                var redirectUri = Request.PathBase + Request.Path + QueryString.Create ( parameters );

                return Challenge (
                    authenticationSchemes: CookieAuthenticationDefaults.AuthenticationScheme,
                    properties: new AuthenticationProperties
                    {
                        RedirectUri = redirectUri
                    } );
            }

            // Retrieve the profile of the logged in user.
            var user = UserManager.GetUser ( result.Principal ) ??
                throw new InvalidOperationException ( "The user details cannot be retrieved." );

            // Retrieve the application details from the database.
            var application = await ApplicationManager.FindByClientIdAsync ( request.ClientId ) ??
                throw new InvalidOperationException ( "Details concerning the calling client application cannot be found." );

            // Retrieve the permanent authorizations associated with the user and the calling client application.
            var authorizations = await AuthorizationManager.FindAsync (
                subject:UserManager.GetUserId ( user ),
                client: await ApplicationManager.GetIdAsync ( application ),
                status: Statuses.Valid,
                type: AuthorizationTypes.Permanent,

                scopes: request.GetScopes () ).ToListAsync ();

            switch ( await ApplicationManager.GetConsentTypeAsync ( application ) )
            {
                // If the consent is external (e.g when authorizations are granted by a sysadmin),
                // immediately return an error if no authorization can be found in the database.
                case ConsentTypes.External when !authorizations.Any ():
                    return Forbid (
                        authenticationSchemes: CookieAuthenticationDefaults.AuthenticationScheme,
                        properties: new AuthenticationProperties ( new Dictionary<string, string>
                        {
                            [ OpenIddictServerAspNetCoreConstants.Properties.Error ] = Errors.ConsentRequired,
                            [ OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription ] =
                                "The logged in user is not allowed to access this client application."
                        } ) );

                // If the consent is implicit or if an authorization was found,
                // return an authorization response without displaying the consent form.
                case ConsentTypes.Implicit:
                case ConsentTypes.External when authorizations.Any ():
                case ConsentTypes.Explicit when authorizations.Any () && !request.HasPrompt ( Prompts.Consent ):
                    // Create the claims-based identity that will be used by OpenIddict to generate tokens.
                    var claimsIdentity = new ClaimsIdentity (
                        authenticationType: CookieAuthenticationDefaults.AuthenticationScheme,
                        nameType: Claims.Name,
                        roleType: Claims.Role );

                    // Add the claims that will be persisted in the tokens.
                    claimsIdentity.SetClaim ( Claims.Subject, UserManager.GetUserId ( user ) );
                            //.SetClaim ( Claims.Email, await UserManager.GetEmailAsync ( user ) )
                            //.SetClaim ( Claims.Name, await UserManager.GetUserNameAsync ( user ) )
                            //.SetClaims ( Claims.Role, ( await UserManager.GetRolesAsync ( user ) ).ToImmutableArray () );

                    // Note: in this sample, the granted scopes match the requested scope
                    // but you may want to allow the user to uncheck specific scopes.
                    // For that, simply restrict the list of scopes before calling SetScopes.
                    claimsIdentity.SetScopes ( request.GetScopes () );
                    claimsIdentity.SetResources ( await ScopeManager.ListResourcesAsync ( claimsIdentity.GetScopes () ).ToListAsync () );

                    // Automatically create a permanent authorization to avoid requiring explicit consent
                    // for future authorization or token requests containing the same scopes.
                    var authorization = authorizations.LastOrDefault ();
                    authorization ??= await AuthorizationManager.CreateAsync (
                        identity: claimsIdentity,
                        subject: UserManager.GetUserId ( user ),
                        client: await ApplicationManager.GetIdAsync ( application ),
                        type: AuthorizationTypes.Permanent,
                        scopes: claimsIdentity.GetScopes () );

                    claimsIdentity.SetAuthorizationId ( await AuthorizationManager.GetIdAsync ( authorization ) );
                    //claimsIdentity.SetDestinations ( GetDestinations );

                    return SignIn ( new ClaimsPrincipal ( claimsIdentity ), CookieAuthenticationDefaults.AuthenticationScheme );

                // At this point, no authorization was found in the database and an error must be returned
                // if the client application specified prompt=none in the authorization request.
                case ConsentTypes.Explicit when request.HasPrompt ( Prompts.None ):
                case ConsentTypes.Systematic when request.HasPrompt ( Prompts.None ):
                    return Forbid (
                        authenticationSchemes: CookieAuthenticationDefaults.AuthenticationScheme,
                        properties: new AuthenticationProperties ( new Dictionary<string, string>
                        {
                            [ OpenIddictServerAspNetCoreConstants.Properties.Error ] = Errors.ConsentRequired,
                            [ OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription ] =
                                "Interactive user consent is required."
                        } ) );

                /*
                // In every other case, render the consent form.
                default:
                    return View ( new AuthorizeViewModel
                    {
                        ApplicationName = await ApplicationManager.GetLocalizedDisplayNameAsync ( application ),
                        Scope = request.Scope
                    } );
                */
            }

        }
        catch ( Exception ex ) 
        {
            throw;
        }

        /*

        try
        {
            // Retrieve the OpenIddict server request from the HTTP context.
            var request = HttpContext.GetOpenIddictServerRequest ();


            // Retrieve the user principal stored in the authentication cookie.
            var result = await HttpContext.AuthenticateAsync ( CookieAuthenticationDefaults.AuthenticationScheme );

            // If the user principal can't be extracted, redirect the user to the login page.
            if ( !result.Succeeded )
            {
                var redirectUri = Request.PathBase + Request.Path + QueryString.Create ( Request.HasFormContentType ? Request.Form.ToList () : Request.Query.ToList () );

                var res =
                Challenge (
                    authenticationSchemes: CookieAuthenticationDefaults.AuthenticationScheme,
                    properties: new AuthenticationProperties
                    {
                        RedirectUri = redirectUri
                    } );

                return res;
            }


            // Create a new claims principal
            var claims = new List<Claim>
            {
                // 'subject' claim which is required
                new Claim(OpenIddictConstants.Claims.Subject, result.Principal.Identity.Name),
                new Claim("some claim", "some value").SetDestinations(OpenIddictConstants.Destinations.AccessToken),
                new Claim(OpenIddictConstants.Claims.Email, "some@email").SetDestinations(OpenIddictConstants.Destinations.IdentityToken)
            };

            var claimsIdentity = new ClaimsIdentity ( claims, CookieAuthenticationDefaults.AuthenticationScheme );

            claimsPrincipal = new ClaimsPrincipal ( claimsIdentity );

            // Set requested scopes (this is not done automatically)
            claimsPrincipal.SetScopes ( request.GetScopes () );

            // Signing in with the OpenIddict authentiction scheme trigger OpenIddict to issue a code (which can be exchanged for an access token)
            return SignIn ( claimsPrincipal, CookieAuthenticationDefaults.AuthenticationScheme );
        }
        catch ( Exception ex ) 
        {
            var msg = ex.Message;
            throw;
        }
        */


        return Ok ();
       
    }

    [HttpPost ( "~/connect/token" )]
    public async Task<IActionResult> Exchange ()
    {
        var request = HttpContext.GetOpenIddictServerRequest () ??
                      throw new InvalidOperationException ( "The OpenID Connect request cannot be retrieved." );

        ClaimsPrincipal claimsPrincipal;

        if ( request.IsClientCredentialsGrantType () )
        {
            // Note: the client credentials are automatically validated by OpenIddict:
            // if client_id or client_secret are invalid, this action won't be invoked.

            var identity = new ClaimsIdentity ( CookieAuthenticationDefaults.AuthenticationScheme );

            // Subject (sub) is a required field, we use the client id as the subject identifier here.
            identity.AddClaim ( OpenIddictConstants.Claims.Subject, request.ClientId ?? throw new InvalidOperationException () );

            // Add some claim, don't forget to add destination otherwise it won't be added to the access token.
            //identity.AddClaim ( "some-claim", "some-value", OpenIddictConstants.Destinations.AccessToken );

            claimsPrincipal = new ClaimsPrincipal ( identity );

            claimsPrincipal.SetScopes ( request.GetScopes () );
        }

        else if ( request.IsAuthorizationCodeGrantType () )
        {
            // Retrieve the claims principal stored in the authorization code
            claimsPrincipal = ( await HttpContext.AuthenticateAsync ( CookieAuthenticationDefaults.AuthenticationScheme ) ).Principal;
        }

        else if ( request.IsRefreshTokenGrantType () )
        {
            // Retrieve the claims principal stored in the refresh token.
            claimsPrincipal = ( await HttpContext.AuthenticateAsync ( CookieAuthenticationDefaults.AuthenticationScheme ) ).Principal;
        }

        else
        {
            throw new InvalidOperationException ( "The specified grant type is not supported." );
        }

        // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
        var result = SignIn ( claimsPrincipal, CookieAuthenticationDefaults.AuthenticationScheme );



        return result;
    }

    [Authorize ( AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme )]
    [HttpGet ( "~/connect/userinfo" )]
    public async Task<IActionResult> Userinfo ()
    {
        var claimsPrincipal = ( await HttpContext.AuthenticateAsync ( CookieAuthenticationDefaults.AuthenticationScheme ) ).Principal;

        return Ok ( new
        {
            Name = claimsPrincipal.GetClaim ( OpenIddictConstants.Claims.Subject ),
            Occupation = "Developer",
            Age = 43
        } );
    }
}

`

Account Controller

` public class AccountController : Controller { #region Constructors

    public AccountController ( NavigationManager navigationManager, ILocalStorageService localStorage )
    {
        if ( navigationManager == null )
            throw new ArgumentNullException ( "FAILED to get nav mgr" );

        NavigationManager = navigationManager;
        LocalStorage = localStorage;
    }

    #endregion

    #region Properties

    
    ILocalStorageService LocalStorage
    { get; set; }



    
    public NavigationManager NavigationManager
    { get; set; }



    #endregion


    #region Methods

    [HttpGet]
    [AllowAnonymous]
    public IActionResult Login ( string returnUrl = null )
    {
        //ViewData [ "ReturnUrl" ] = returnUrl;





        return Ok ( returnUrl );
    }

    [HttpPost]
    

    //[AllowAnonymous]
    //[ValidateAntiForgeryToken]
    public async Task<UserInfo> Login ( [FromBody] LoginModel model )
    {
        UserInfo user = null;
        ClaimsPrincipal claimsPrincipal = null;

        try
        {



            var claims = new List<Claim>
            {
                new Claim ( ClaimTypes.Name, model.Username )
            };

            var claimsIdentity =
                new ClaimsIdentity ( claims, CookieAuthenticationDefaults.AuthenticationScheme );

            claimsPrincipal = 
                new ClaimsPrincipal ( claimsIdentity );

            await HttpContext.SignInAsync ( CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal );

            var isAuthenticated = claimsIdentity.IsAuthenticated;

            user =
                new UserInfo ()
                {
                    UserName = model.Username,
                    IsAuthenticated = isAuthenticated,
                };

            if ( user == null )
                throw new NullReferenceException ( "FAILED to create user info" );

        }
        catch ( Exception ex ) 
        { 
            var message = ex.ToString ();
        }




        return user;

    }

    public async Task<IActionResult> Logout ()
    {
        await HttpContext.SignOutAsync ();

        return Ok ();
    }


    #endregion
}

`

Issue Analytics

  • State:closed
  • Created 6 months ago
  • Comments:16 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
dgxhubbardcommented, Mar 31, 2023

Thanks I will remove the account controller and look at minimal api handler

1reaction
dgxhubbardcommented, Mar 27, 2023

AH HA!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Choosing the right flow - OpenIddict
Resource owner password credentials flow (not recommended for new applications). Directly inspired by basic authentication, the resource owner password ...
Read more >
Setting up an Authorization Server with OpenIddict - Part III
For now, we need to focus on the Client Credentials Flow. When the request enters the Exchange action, the client credentials (ClientId and ......
Read more >
Implement a GRPC API with OpenIddict and the OAuth client ...
The client application uses the OAuth2 client credentials flow ... The GRPC API uses introspection to validate and authorize the access.
Read more >
Client credentials flow fails with 401 Not Authorized from ...
I am successfully connecting to the auth server, getting an access token and passing it along to the resource server. However the request...
Read more >
Combining client credentials flow with authorization code ...
I get the client credentials flow and the authorization code flow with integrated win-auth up and running by looking at the Openiddict ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found