Resource Owner Password Grant - markglibres/identityserver4-mongodb-redis GitHub Wiki
Run sample IdentityServer with docker hub image
Run sample IdentityServer with local docker
Configure for Resource Owner Password grant
Sample on how to configure API client
- Create docker-compose file i.e.
docker-compose-identity.yaml
and pull image frombizzpo/identityserver4
. For example:
version: '3.4' services: identity: image: bizzpo/identityserver4 environment: - Environment=Development - "Identity__Mongo__ConnectionString=mongodb://root:foobar@mongodb:27017/?readPreference=primaryPreferred&appname=identityserver" - Identity__Mongo__Database=Identity - Identity__Redis__ConnectionString=redis - Identity__Redis__Db=-1 - Identity__Redis__Prefix=identity container_name: identity depends_on: - redis - mongodb ports: - 5000:80 networks: - identity restart: always redis: image: bitnami/redis ports: - 6379:6379 environment: - ALLOW_EMPTY_PASSWORD=yes networks: - identity restart: always mongodb: image: mongo:4.2.8 environment: - MONGO_INITDB_ROOT_USERNAME=root - MONGO_INITDB_ROOT_PASSWORD=foobar ports: - 27017:27017 networks: - identity restart: always networks: identity: driver: bridge 2. Run docker-compose file
bash
docker-compose -f docker-compose-identity.yaml up 3. Execute get token with the following details:
bash
- method = POST * url = http://localhost:5000/connect/token * grant_type = password * username = dev * password = hardtoguess * scope = myapi.access openid offline_access * client_id = spaWeb * client_secret = hardtoguess ```Click here to see more seeded sample clients and grant types
- Clone this repository
git clone [email protected]:markglibres/identityserver4-mongodb-redis.git 2. Build docker images
bash
docker-compose -f src/docker-compose.yaml build 3. Run docker containers
bash
docker-compose -f src/docker-compose.yaml up ```4. Install Postman UI and import the postman folder /postman
5. On Postman UI, run sample Login, Logout, Refresh Token and Get User endpoints with `identity_docker` environment
- Create empty dotnetcore API project
- Install NuGet package BizzPo.IdentityServer
- In
appsettings.json
, add configuration for mongodb and redis
"Identity": { "Authority": "http://localhost:5000", /* url of your identity server */ "Mongo": { "ConnectionString": "mongodb://root:foobar@localhost:27017/?readPreference=primaryPreferred&appname=identityserver", /connection string for your mongodb server/ "Database": "Identity" }, "Redis": { "ConnectionString": "localhost", "Db": -1, "Prefix": "identity" } } 4. In `Startup.cs -> ConfigureServices`, register MongoDb and Redis caching
csharp
services.AddIdentityServerMongoDb(provider => new DefaultCorsPolicyService(provider.GetService<ILogger>()) { AllowAll = true, //configure allowed origins //AllowedOrigins = new List { } }) .AddRedisCache() .AddDeveloperSigningCredential(); ``` Build the project and run. You now have your first IdentityServer4 running, but to start generating tokens, we have to configure the clients, api resources, scopes and identity resources.
- In
Program.cs
, initialize seeder service
public static async Task Main(string[] args) { var host = CreateHostBuilder(args).Build(); await host.Services.Initialize(); await host.RunAsync(); } 2. Using interface `ISeeder<T>`, create seeder class for types Clients, ApiResources, ApiScopes and IdentityResources. For example:
csharp
public class SeedApiScopes : ISeeder { public IEnumerable GetSeeds() => new[] { new ApiScope("myapi.access", "Access API Backend") } } 3. In `Startup.cs`, register the seeder classes
csharp
services.AddIdentityServerMongoDb(provider => // codes removed for brevity .SeedClients() .SeedApiResources() .SeedApiScope() .SeedIdentityResource(); ```4. Build and run the project to generate tokens.
- Create
User
class and inherit fromIdentityUser
, or you can implement from partial classApplicationUser
- Create
Role
class and inherit fromIdentityRole
, or you can implement from partial classApplicationRole
- In
Startup.cs
, configure Resource Owner Password grant type
services.AddIdentityServerMongoDb(provider => // codes removed for brevity .AddResourceOwnerPassword<ApplicationUser, ApplicationRole>(); ```4. Build and run the project, but you need to populate your users store to start generating token. See next steps on how to seed users.
- In
Program.cs
, initialize seeder service for users
public static async Task Main(string[] args) { var host = CreateHostBuilder(args).Build(); // codes removed for brevity await host.Services.Initialize(); await host.RunAsync(); } 2. Create seeder class for users and inherit from `ISeeder<T>` where T is your user type. i.e. ApplicationUser. For example:
csharp
public class SeedUsers : ISeeder { private readonly IPasswordHasher _passwordHasher; public SeedUsers(IPasswordHasher passwordHasher) { _passwordHasher = passwordHasher; } public IEnumerable GetSeeds() => new List
{ new ApplicationUser { Id = Guid.NewGuid().ToString(), UserName = "dev", PasswordHash = _passwordHasher.HashPassword(null, "hardtoguess"), EmailConfirmed = true } } } 3. In `Startup.cs`, register the seeder class
csharp
services.AddIdentityServerMongoDb(provider => // codes removed for brevity .AddResourceOwnerPassword<ApplicationUser, ApplicationRole>() .SeedUsers<ApplicationUser, SeedUsers>() ```4. Build and run the project. You should now be able to generate tokens using resource owner password grant type.
The project contains an optional seed data that any developer can start generating tokens. Add the whole block on configure services
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServerMongoDb(provider => new DefaultCorsPolicyService(provider.GetService<ILogger<DefaultCorsPolicyService>>()) { AllowAll = true, } .AddRedisCache() .AddDeveloperSigningCredential() .AddResourceOwnerPassword<IdentityServer_ApplicationUser, ApplicationRole>() .SeedUsers<ApplicationUser, SeedUsers<ApplicationUser>>() .SeedClients<SeedClients>() .SeedApiResources<SeedApiResources>() .SeedApiScope<SeedApiScopes>() .SeedIdentityResource<SeedIdentityResources>();}
Seeded values can be found here
Steps below is for a sample C# API project
- Create an empty API project
- Install the following NuGet packages:
- Microsoft.AspNetCore.Authentication.JwtBearer * IdentityModel.AspNetCore.OAuth2Introspection * IdentityModel.AspNetCore.AccessTokenValidation ```3. Configure authorization with JWT bearer token:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => {
options.Authority = "http://localhost:5000";
options.Audience = "myapi";
options.RequireHttpsMetadata = false;
//if token does not contain a dot, it is a reference token
//if it's a reference token, will forward it to introspection
options.ForwardDefaultSelector = Selector.ForwardReferenceToken("introspection"); });
```csharp
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { // codes removed for brevity
}) .AddOAuth2Introspection("introspection", options => { options.Authority = "http://localhost:8989"; options.ClientId = "myapi"; // the API secret value configured in previous step options.ClientSecret = "hardtoguess"; // optional: use non-ssl for discovery endpoint, by default uses SSL
options.DiscoveryPolicy = new DiscoveryPolicy { RequireHttps = false }; }); ```5. Configure pipeline to use authorization.
```csharp
app.UseIdentityServer(); app.UseAuthentication();
app.UseAuthorization();
```6. Authorize controllers and set the default authorization scheme
```csharp
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class MyApiController : ControllerBase { } ```