Dangl.Identity Client Libraries
Changelog
Online Documentation
Dangl.Identity is an OpenID / OAuth2 capable server that offers single sign on functionalities.
It's primary is available at https://identity.dangl-it.com with a fallback at https://identity.dangl-it.de.
It works with all OpenID Connect compatible clients and it's configuration is available here.
The preview is available at https://identity-dev.dangl-it.com.
The Dangl.Identity.Client libraries offer specialised classes and utilities that make integrating and connecting with Dangl.Identity easy.
Default Configuration
By default, the identity provider is expected to be reachable at https://identity.dangl-it.com
.
Dangl.Identity.Client
This project includes the DanglIdentityLoginHandler
that offers JWT / OAuth2 login and refresh functionalities for clients that have the ResourceOwnerPasswordGrant
enabled.
The DanglIdentityClientCredentialsLoginHandler
can be used with clients that have the ClientCredentials
grant enabled, for example in server-side applications.
Both login handlers require an instance of HttpClient
to be injected at creation. It is advised that the HttpClientFactory
from the Microsoft.Extensions.Http
package is used
to efficiently manage the lifetime of HttpClient
instances.
Angular Client
Web applications that use the integrated Dangl.Identity JWT endpoints from the Dangl.Identity.Client.MVC
package can use the @dangl/angular-dangl-identity-client
npm package.
This package offers a generated client for the Dangl.Identity JWT endpoints and manages local storage of JWT tokens. The client assumes that the endpoint is available on the current host, otherwise it uses an injection parameter:
@Optional() @Inject(DANGL_IDENTITY_CLIENT_API_BASE_URL) baseUrl?: string
The Angular client works by adding an Http interceptor that attaches the JWT token to all requests. Additionally, it provides the following services:
AuthenticationService
The AuthenticationService
offers methods to login and logout. This only works when the backend is configured to accept the ResourceOwnerPasswordGrant
grant type.
AuthenticationMessenger
The AuthenticationMessenger
offers an observable that can be used to watch for changes in the authentication state. It will provide additional information contained in the JWT, like the user name and roles.
Additionally, if cookie authentication is used and the frontend does not have direct access to JWTs, then you can call AuthenticationMessenger.refreshUserInfoFromServer()
to let the service fetch the current user info from the backend and raise the internal observables.
JwtTokenService
The JwtTokenService
offers methods to retrieve the current JWT token, to check if it is expired and to update it. It will internally handle refreshing the token as well, if there is a refresh token present.
Install Dependencies
The package requires a peer dependency of @auth0/angular-jwt
which must be manually
installed in the consuming project.
Reference Module
Just import the DanglIdentityModule
in your app.
import { AppComponent } from './app.component';
import { DanglIdentityModule } from '@dangl/angular-dangl-identity-client';
@NgModule({
imports: [
DanglIdentityModule
],
bootstrap: [AppComponent]
})
export class AppModule { }
Other case we use configuration with DI-based approach and avoid module
Just provide the interceptor in your config file.
We use provider provideHttpClient()
instead of HttpClientModule
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { JwtInterceptorService } from '@dangl/angular-dangl-identity-client';
export const appConfig: ApplicationConfig = {
providers: [
...
provideHttpClient(withInterceptorsFromDi()),
{
provide: HTTP_INTERCEPTORS,
useClass: JwtInterceptorService,
multi: true
}
]
};
Then, in main.ts:
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));
Validate Requests for Including JWT Authorization Header
By default, the provided JwtInterceptorService
will attach JWT bearer tokens to all requests, if tokens are present.
If you want to control whether or not you want to include them, you need to provide the following optional dependency:
@Optional()
@Inject(DANGL_IDENTITY_REQUEST_VALIDATOR)
private requestValidator: IDanglIdentityRequestValidator
In the model, you can provide it like this:
providers: [
{
provide: DANGL_IDENTITY_REQUEST_VALIDATOR,
useClass: MyCustomRequestValidator,
}
]
Login / Logout
Here's an example login functionality:
import { AuthenticationService,
AuthenticationMessenger } from '@dangl/angular-dangl-identity-client';
this.isAuthenticatedSubscription = this.authenticationMessenger
.isAuthenticated
.subscribe(ia => this.isAuthenticated = ia);
login() {
this.requestEnRoute = true;
this.authenticationService
.loginWithToken(this.credentials.identifier, this.credentials.password)
.subscribe(r => {
this.requestEnRoute = false;
if (r) {
this.showLoginError = false;
this.errorCount = 0;
this.router.navigateByUrl('/');
} else {
this.showLoginError = true;
this.errorCount++;
}
});
}
AuthenticationMessenger
The AuthenticationMessenger
class can be used to watch for changes in the authentication. It will automatically try to refresh the token if a refresh token
is present and the current token is expired on load.
Assembly Strong Naming & Usage in Signed Applications
This module produces strong named assemblies when compiled. When consumers of this package require strongly named assemblies, for example when they
themselves are signed, the outputs should work as-is.
The key file to create the strong name is adjacent to the csproj
file in the root of the source project. Please note that this does not increase
security or provide tamper-proof binaries, as the key is available in the source code per
Microsoft guidelines