Dangl.Identity Client Libraries

    Build Status

    Changelog
    Online Documentation

    Default Configuration

    By default, the identity servers are expected to be reachable at https://identity.dangl-it.com and https://identity.dangl-it.de. Fallback happens automatically to the latter on if the former is unreachable.

    Dangl.Identity.Client

    This project includes the DanglIdentityLoginHandler that offers JWT / OAuth2 login and refresh functionalities.

    Dangl.Identity.OAuth

    This project includes utilities for integrating Dangl.Identity in Asp.Net Core web applications.

    Dangl.Identity.Client.App

    This is a generated client to be used in apps to connect with web services that use Dangl.Identity. The code is generated via nSwag.

    Asp.Net Core Identity Server Side Integration

    Add the following to the ConfigureServices method in your Startup:

    services.AddDbContext<IntegrationTestsContext>(o => o.UseSqlite(sqliteConnectionString));
    
    var danglIdentityServerConfig = new DanglIdentityServerConfiguration()
        .SetClientId(_clientId)
        .SetClientSecret(_clientSecret)
        .SetRequiredScope(_requiredScopes)
        .SetBaseUri(_baseUri)
        .SetFallbackBaseUri(_fallbackBaseUri);
    
    services.AddMvcWithDanglIdentity<IntegrationTestsContext, IntegrationTestsUser, IntegrationTestsRole>(danglIdentityServerConfig);
    

    With clientId, clientSecret and requiredScopes being the respective values as registered with Dangl.Identity.
    There are more optional parameters present. Use relativeLoginUrl to communicate the apps specific login path. This is used to generate correct links for users when they confirm their emails or reset passwords.

    By default, the option UseMemoryCacheUserInfoUpdater is set to true. This means that the configuration automatically adds the default Asp.Net Core IMemoryCache implementation and uses it in the default MemoryCacheUserInfoUpdaterCache : IUserInfoUpdaterCache. This is required, because Jwt tokens are checked for user profile data which is then persisted to the local database, e.g. for creating UserId references in foreign keys. To not have to do database roundtrips, each single Jwt token is only checked once, then only again after it has expired and was refreshed.

    Additionally, if Jwt tokens are used for authentication and you want to synchronize user data to a local database, add app.UseDanglIdentityJwtTokenUserInfoUpdater() after UseAuthentication, like in the following example:

    app.UseAuthentication();
    
    app.UseDanglIdentityJwtTokenUserInfoUpdater();
    
    app.UseMvc();
    

    The DanglIdentityUserInfoUpdater will evaluate requests that contain a Jwt token and create or update the user data in the database. Tokens are cached in the provided IUserInfoUpdaterCache, meaning there should only be a single database hit for every token. With a default expiration time of one hour, most requests will not hit the database while still providing relatively up-to-date user data. If the token changes, the database will be hit again.

    IUserInfoService

    Dangl.Identity.OAuth provides an IUserInfoService:

    namespace Dangl.Identity.OAuth.Services
    {
        public interface IUserInfoService
        {
            Task<bool> UserIsAuthenticatedAsync();
            Task<bool> ClientIsAuthenticatedAsync();
            Task<Guid> GetCurrentUserIdAsync();
            Task<Guid> GetCurrentClientIdAsync();
            Task<string> GetUserIpAddressAsync();
            Task<List<Claim>> GetUserClaimsAsync();
            Task<List<Claim>> GetClientClaimsAsync();
        }
    }
    

    Notes:

    • UserIsAuthenticatedAsync returns only true if an actual user is authenticated, it is false for client credential grants
    • GetUserClaimsAsync returns all claims
    • GetClientClaimsAsync returns only claims whose type starts with client_

    Integration with Dangl.Identity.TestHost

    When you have multiple TestHost instances, there might be problems with AuthorizationPolicy. The Dangl.Identity server / test host defines a policy that is somehow shared across all TestServer instances.

    Add this to your Setup for the integration tests:

    var danglIdentityServerConfig = new DanglIdentityServerConfiguration()
        .SetAuthorizationSetupAction(o =>
        {
            o.AddPolicy("scope01", builder => builder.RequireScope("integration_tests"));
            o.AddPolicy("scope02", builder => builder.RequireScope("different_scope"));
            o.AddPolicy("DelegatedAccountAccess", builder => builder.RequireAssertion(c => { return true; }));
        });
    

    TestHost Configuration

    When working with the Dangl.Identity.TestHost and Jwt Bearer Authentication, e.g. with Dangl.Identity.OAuth, the base uri for Dangl.Identity should be set to the test hosts uri value of https://dangl-identity-testhost so that Jwt token validation does work as expected.

    Login Method in Your Controllers

    Use dependency injection to get a service of type IDanglIdentitySignInManager to perform a cookie-backed sign in attemtp via identifier (username or email) and password.

    Included DanglIdentityController

    There are custom endpoints for the following actions available:

    Login with Cookie

    POST /identity/login
    Body:
        {
            "identifier": <username or email>,
            "password": <password",
            "staySignedIn": <boolean>
        }
    

    This accepts an optional redirectUrl query parameter, e.g.

    POST /identity/login?redirectUrl=home
    

    Logout with Cookie

    DELETE /identity/login
    

    Login and Return Jwt Bearer Token

    POST /identity/token-login
    Body:
        {
            "identifier": <username or email>,
            "password": <password"
        }
    

    Response

    {
        "accessToken": string
        "identityToken": string
        "tokenType": string
        "refreshToken": string
        "errorDescription": string
        "expiresIn": number
    }
    

    Refresh Jwt Bearer Token

    POST /identity/token-refresh
    Body:
        {
            "refreshToken": <refresh token>
        }
    

    Response

    {
        "accessToken": string
        "identityToken": string
        "tokenType": string
        "refreshToken": string
        "errorDescription": string
        "expiresIn": number
    }
    
    • Improve this Doc
    Back to top © Dangl IT - Georg Dangl