Giter Club home page Giter Club logo

openiddict-ui's Introduction

Type Description Badge
Build Build status build
OpenIddict-UI API API's for managing OpentIddict Scopes and Applications. NuGet Release
OpentIddict-UI Identity API API's for managing ASP.NET Core Identity types (Accounts, Roles, etc.). NuGet Release

OpenIddict UI

A first step to provide some headless UI features to the OpenIddict stack.

Please note that this project does not provide you a ready to use UI instead provides you the required services that allow you to build one. You can use the samples as a starting point though.

Currently it provides API's for managing Scopes and Applications.

On top of that it ships API's for the Usermanagement when using ASP.NET Core Identity.

As a goodie the samples demonstrates this features by an Angular SPA client that uses the Authorization Code flow.

SPA Client

Running the sample

Assuming you downloaded the sources and opened VS Code in the root repo directory you should be good to go! Ahh and of course you need .NET Core and node.js installed on your development environment.

Running the sample Server

  1. Open the integrated terminal in VS Code and type
dotnet build

That ensures you are able to build the dotnet related stuff!

  1. Go to the VS Code Debug tab (Ctrl+Shift+D) and run the Server project.

Develop the sample Client (Angular based frontend)

  1. Make sure you installed Node.js.

If you develop in a devcontainer then you are already good to go!

  1. First run the backend (see previous chapter)

  2. After the Server is running navigate within your favorite command line to the Client directory and type:

npm i

This will install all the Client's required dependencies.

npm run start

This will start Angular's development server.

  1. Now open your browser of choice and point to the well known Angular dev url.
http://localhost:4200

You should see now the login screen. You can now login with the pre-configured administrator users account which is:

Using it

Follow the original setup of the OpenIddict in the Startup.ConfigureServices(...) - method and add your required additional extension hooks AddUIStore(...), AddUIApis(...), AddUIIdentityStore<TIdentityUser>(...) and AddUIIdentityApis<TIdentityUser>().

...
services.AddOpenIddict()
  // Register the OpenIddict core components.
  .AddCore(options =>
  {
    ...
  })
  // Register the OpenIddict server components.
  .AddServer(options =>
  {
    ...
  })
  // Register the OpenIddict validation components.
  .AddValidation(options =>
  {
    ...
  })
  // Register the EF based UI Store for OpenIddict related entities.
  .AddUIStore(options =>
  {
    options.OpenIddictUIContext = builder =>
      builder.UseSqlite(Configuration.GetConnectionString("DefaultConnection"),
        sql => sql.MigrationsAssembly(typeof(Startup)
                  .GetTypeInfo()
                  .Assembly
                  .GetName()
                  .Name));
  })
  // Register the APIs for the EF based UI Store based on OpenIddict.
  .AddUIApis(options =>
  {
    // Tell the system about the allowed Permissions it is built/configured for.
    options.Permissions = new List<string>
    {
      Permissions.Endpoints.Authorization,
      Permissions.Endpoints.Logout,
      Permissions.Endpoints.Token,
      Permissions.GrantTypes.AuthorizationCode,
      Permissions.GrantTypes.Password,
      Permissions.GrantTypes.RefreshToken,
      Permissions.ResponseTypes.Code,
      Permissions.Scopes.Email,
      Permissions.Scopes.Profile,
      Permissions.Scopes.Roles,
      Permissions.Prefixes.Scope + "demo_api"
    }
  })
  // Register the EF based UI Store for the ASP.NET Identity related entities.
  .AddUIIdentityStore<ApplicationUser>(options =>
  {
    options.OpenIddictUIIdentityContext = builder =>
     builder.UseSqlite(Configuration.GetConnectionString("DefaultConnection"),
       sql => sql.MigrationsAssembly(typeof(Startup)
                 .GetTypeInfo()
                 .Assembly
                 .GetName()
                 .Name));
  })
  // Register the APIs for the EF based UI Store based on ASP.NET Identity.
  .AddUIIdentityApis<ApplicationUser>();
...

Change the type of primary key used for IdentityUser

If your ApplicationUser class derives from an IdentityUser class where the key type is specified (e.g. IdentityUser<Guid>) this key must also be supplied to AddUIIdentityStore and AddUIIdentityApis. e.g.

An example project using INT as the primary key is included in the samples/ServerWithCustomKey project.

...
  .AddUIIdentityStore<ApplicationUser, int>(options =>
  {
    ...
  })
  // Register the APIs for the EF based UI Store based on ASP.NET Identity.
  .AddUIIdentityApis<ApplicationUser, int>();
...

Thoughts and ideas

The project is still very young and there are a lot of ideas like:

  • Provide API's for the Authorization and Token entities (if then really required).
  • Provide a ASP.NET Razor Page based UI.
  • Possibility to manage translated display names based on supported languages etc.

openiddict-ui's People

Contributors

fairlieagile avatar thomasduft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openiddict-ui's Issues

Integration test for the private resource API

Hello @thomasduft

I have quickly added the integration tests for both public and private resource API (api/Resource/public and api/Resource/private) to validate the case when the API and the Server are not in the same app.

I always get the success status code from the public API, which is good, but the private API returns the internal server error due to the token validation failed, "No connection could be made because the target machine actively refused it". I ensure the token is valid and the Server is running properly since it returns the correct user info.

The interesting is, if I run the Server manually, all tests are passed. This means the token validation is success.

Is there something that I missed to get it run correctly?

CRUD user profile

Hi Thomas,

Am I correct that the account API is only for the user identity but not for the user profile? If yes, how should I deal with the user profile? Should I create its own API?
Here is my simple user class.

public class MyUser: IdentityUser
{
    public MyUser()
    {
    }

    public MyUser(string username)
        : base(username)
    {
    }

    public string? Name { get; set; }
    public string? FirstName { get; set; }
}

Best regards,

Xiaoyang

Excuse me, I want to ask about database update

When I run dotnet ef database update, I run into this error: More than one DbContext was found. Specify which one to use

I notice that you have more than 1 DbContext. So how to fix this?

How can I add more scopes?

If I delete some old scope, they doesnt appear in the request.GetScopes. That is true, but, when I add one more scope to the db and the client, the request.GetScopes() does not return that new scope, only the old five?

Please help !!!!

deploy to production

hello,

i try to deploy to production.

the following error occur.
System.Security.Cryptography.CryptographicException: Access is denied.

what is the issue?

Add possibility to use api without ADMIN role

Hi,

I use your API using client credential flow, and my application do not have Administrator role and therefore I had to create a custom IAuthorizationHandler with verification of specific claims in order to allow the usage of API.
It would be great to find a prettier to do this. Do you have any ideas?

public class SpecificApiAuthorizationHandler : IAuthorizationHandler
    {

        private readonly OpenIddictConfigurationOptions _openIdDictSettings;
        private readonly HashSet<string> _authorizedScopes;

        public SpecificApiAuthorizationHandler(
            IOptions<OpenIddictConfigurationOptions> openIdDictOptions)
        {
            _openIdDictSettings = (openIdDictOptions ??
                throw new ArgumentNullException(nameof(openIdDictOptions))).Value;

            _authorizedScopes = new HashSet<string>(_openIdDictSettings.AuthorizedApiScope, StringComparer.OrdinalIgnoreCase);
        }

        public Task HandleAsync(AuthorizationHandlerContext context)
        {

            //if (context.Resource is HttpContext httpContext)
            //{
            //    var endpoint = httpContext.GetEndpoint();                
            //    var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
            //}

            var pendingRequirements = context.PendingRequirements.ToList();

            foreach (var requirement in pendingRequirements)
            {
                if (requirement is RolesAuthorizationRequirement rolesAuthorizationRequirement)
                {
                    if (rolesAuthorizationRequirement.AllowedRoles.Contains(Roles.ADMINISTRATOR_ROLE))
                    {
                        if (IsAdmin(context.User, context.Resource) || HasClaimAuthorizedScope(context.User, context.Resource))
                        {
                            context.Succeed(rolesAuthorizationRequirement);
                        }
                    }
                }
            }
            return Task.CompletedTask;
        }


        private bool IsAdmin(ClaimsPrincipal user, object? resource)
        {
            return user.IsInRole(Roles.ADMINISTRATOR_ROLE);
        }

        private bool HasClaimAuthorizedScope(ClaimsPrincipal user, object? resource)
        {
            return user.HasClaim(c => c.Type == Claims.Scope
                && c.Issuer.Equals(_openIdDictSettings.Authority, StringComparison.OrdinalIgnoreCase)
                && c.Value.Split(" ").Any(s => _authorizedScopes.Contains(s)));

        }
    }

UI Views request

Hello can please share some UI Views samples so we can adopt/tailor or begin from it

Excuse me, I want to ask about using docker with your project

Everything run fine when I ran it without docker, but when I use docker, I ran into this error: System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'. when I use Postman to get the Api (https://localhost:5001/api/Resource/private) after Login.

Here is my Docker compose:

version: '3'
services:
api:
build: Api/
ports:
- "5002:80"
- "5001:443"
environment:
ASPNETCORE_URLS: "https://+;http://+"
ASPNETCORE_HTTPS_PORT: "5001"
ASPNETCORE_ENVIRONMENT: "Development"
volumes:
- ${APPDATA}\microsoft\UserSecrets:/root/.microsoft/usersecrets
- ${USERPROFILE}.aspnet\https:/root/.aspnet/https/
server:
build: openiddict-ui/
ports:
- "4999:80"
- "5000:443"
environment:
ASPNETCORE_URLS: "https://+;http://+"
ASPNETCORE_HTTPS_PORT: "5000"
ASPNETCORE_ENVIRONMENT: "Development"
volumes:
- ${APPDATA}\microsoft\UserSecrets:/root/.microsoft/usersecrets
- ${USERPROFILE}.aspnet\https:/root/.aspnet/https/

Here is my Dockerfile Sever:

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
RUN dotnet tool install -g dotnet-ef
ENV PATH $PATH:/root/.dotnet/tools
RUN dotnet ef --version
RUN apt-get update
RUN apt-get -y install sqlite3 libsqlite3-dev
WORKDIR /app

COPY .sln ./
COPY samples/Server/
.csproj ./samples/Server/
COPY tests/.csproj ./tests/
COPY src/suite/OpenIddict.UI.Suite.Api/
.csproj ./src/suite/OpenIddict.UI.Suite.Api/
COPY src/suite/OpenIddict.UI.Suite.Core/.csproj ./src/suite/OpenIddict.UI.Suite.Core/
COPY src/openiddict/OpenIddict.UI.Api/
.csproj ./src/openiddict/OpenIddict.UI.Api/
COPY src/openiddict/OpenIddict.UI.Infrastructure/.csproj ./src/openiddict/OpenIddict.UI.Infrastructure/
COPY src/identity/OpenIddict.UI.Identity.Api/
.csproj ./src/identity/OpenIddict.UI.Identity.Api/
COPY src/identity/OpenIddict.UI.Identity.Core/.csproj ./src/identity/OpenIddict.UI.Identity.Core/
COPY src/identity/OpenIddict.UI.Identity.Infrastructure/
.csproj ./src/identity/OpenIddict.UI.Identity.Infrastructure/
RUN dotnet restore
COPY . ./

WORKDIR /app/samples/Server
RUN dotnet build -c Release -o out

WORKDIR /app/tests
RUN dotnet build -c Release -o out

WORKDIR /app/src/suite/OpenIddict.UI.Suite.Api
RUN dotnet build -c Release -o out

WORKDIR /app/src/suite/OpenIddict.UI.Suite.Core
RUN dotnet build -c Release -o out

WORKDIR /app/src/openiddict/OpenIddict.UI.Api
RUN dotnet build -c Release -o out

WORKDIR /app/src/openiddict/OpenIddict.UI.Infrastructure
RUN dotnet build -c Release -o out

WORKDIR /app/src/identity/OpenIddict.UI.Identity.Api
RUN dotnet build -c Release -o out

WORKDIR /app/src/identity/OpenIddict.UI.Identity.Core
RUN dotnet build -c Release -o out

WORKDIR /app/src/identity/OpenIddict.UI.Identity.Infrastructure
RUN dotnet build -c Release -o out

WORKDIR /app/samples/Server
RUN dotnet ef database update -c ApplicationDbContext
RUN dotnet ef database update -c OpenIddictUIContext
RUN dotnet ef database update -c OpenIddictUIIdentityContext
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "Server.dll"]

Here is my Dockerfile Api:

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
RUN apt-get update
RUN apt-get -y install sqlite3 libsqlite3-dev
WORKDIR /app/api

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app/api
COPY --from=build-env /app/api/out .
ENTRYPOINT ["dotnet", "Api.dll"]

IApplicationService.UpdateAsync corrupts ClientSecret

Not sure if it is meant to be used like this, but after updating an existing application the ClientSecret is changed.

var app = await _apps.GetAsync(appId);

var param = new ApplicationParameter()
{
   [...]
   ClientSecret = app.ClientSecret,
   [...]
}

await _apps.UpdateAsync(param);

Leaving the ClientSecret at its initial value of null will cause an exception, too.

So how am I supposed to update an existing application without changing the ClientSecret?

Allow generic types for IdentityUser key

The current code allows for the application user to be inherited from IdentityUser only. But IdentityUser can have it's primary key defined as a generic e.g. IdentityUser or IdentityUser

public class ApplicationUser : IdentityUser<Guid> { }

The constraints throughout this project restrict the application user to being of type IdenityUser (where TApplicationUser : IdentityUser)

To allow for different key types these constraints could be redefined as class only (e.g. this is how UserManager class handles this):

public static OpenIddictBuilder AddUIIdentityStore<TApplicationUser>(
  this OpenIddictBuilder builder,
  Action<OpenIddictUIIdentityStoreOptions> storeOptionsAction = null
) where TApplicationUser : class, new()

Or the code could be modified to use a generic interface e.g.

public static OpenIddictBuilder AddUIIdentityStore<TApplicationUser>(
  this OpenIddictBuilder builder,
  Action<OpenIddictUIIdentityStoreOptions> storeOptionsAction = null
) where TApplicationUser : IdentityUser, new()
{
  return AddUIIdentityStore<TApplicationUser, string>(builder, storeOptionsAction);
}

public static OpenIddictBuilder AddUIIdentityStore<TApplicationUser, TKey>(
  this OpenIddictBuilder builder,
  Action<OpenIddictUIIdentityStoreOptions> storeOptionsAction = null
) 
  where TKey: IEquatable<TKey>
  where TApplicationUser : IdentityUser<TKey>, new()
{
   builder.Services.AddInfrastructureServices<TApplicationUser, TKey>();

   builder.Services
     .AddOpenIddictUIIdentityStore<OpenIddictUIIdentityContext>(storeOptionsAction);

  return builder;
}

User change own password

Hi Thomas,

I have a concern regarding how a user can change his own password.
From my understanding, the APIs are more or less designed for an user admin. While this is fine probably for most use cases, an user might want to change his own password since he does not want the admin to know his password. At the moment, it seems to me that it is not possible for a non-admin role, or did I miss something?

Best regards,

Xiaoyang

Remove dependency to Microsoft.AspNetCore.Mvc.Core

There are a few dependencies to Microsoft.AspNetCore.Mvc.Core which seems to not be needed (at least I was able to build with them removed) and it's causing issues when trying to build a self-contained executable cause it seems to have old and outdated dependencies itself.

tomware.OpenIddict.UI.Identity.Api 1.7.0 -> Microsoft.AspNetCore.Mvc.Core 2.2.5 -> Microsoft.Extensions.DependencyModel 2.1.0 -> Microsoft.DotNet.PlatformAbstractions 2.1.0 -> System.IO.FileSystem 4.0.1 -> runtime.unix.System.IO.FileSystem 4.3.0 -> System.Runtime.InteropServices (>= 4.3.0)  [/src/Solution.sln]
tomware.OpenIddict.UI.Identity.Api 1.7.0 -> Microsoft.AspNetCore.Mvc.Core 2.2.5 -> Microsoft.Extensions.DependencyModel 2.1.0 -> Microsoft.DotNet.PlatformAbstractions 2.1.0 -> System.Runtime.InteropServices (>= 4.1.0) [/src/Solution.sln]

Can this reference be removed?

As a work around I got it working by adding this to my csproj:

<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />

sql server

Hey!
Tell me, please, how to switch the database to sql server?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.