NAME
Dancer2::Plugin::OIDC - OIDC protocol integration for Dancer2
DESCRIPTION
This plugin makes it easy to integrate the OpenID Connect protocol into a Dancer2 application.
It essentially uses the OIDC-Client distribution.
METHODS
BUILD
Code executed once the plugin has been created.
Depending on the configuration, creates and keeps in memory one or more clients (OIDC::Client stateless objects) and automatically adds the callback routes to the application.
METHODS ADDED TO THE APPLICATION
oidc( $provider )
# with just one provider
my $oidc = oidc;
# or
my $oidc = oidc('my_provider');
# with several providers
my $oidc = oidc('my_other_provider');
# or
my $oidc = oidc(); # here, you must define a default provider in the configuration
Creates and returns an instance of OIDC::Client::Plugin with the data from the current request and session.
If several providers are configured, the $provider parameter is mandatory unless the default_provider configuration entry is defined (see OIDC::Client::Config).
This is the application's entry point to the library. Please see the OIDC::Client::Plugin documentation to find out what methods are available.
CONFIGURATION
Section to be added to your configuration file :
plugins:
OIDC:
provider:
my_provider:
id: "my-client-id"
secret: "xxxxxxxxx"
well_known_url: "https://yourprovider.com/oauth2/.well-known/openid-configuration"
signin_redirect_path: "/oidc/login/callback"
scope: "openid profile roles email"
expiration_leeway: 60
This is an example, see the detailed possibilities in OIDC::Client::Config.
SAMPLES
Here are some samples by category. Although you will have to adapt them to your needs, they should be a good starting point.
Setup
To setup the plugin when the application is launched :
package MyApp;
use Dancer2;
use Dancer2::Plugin::OIDC;
Authentication
To authenticate the end-user :
# Authentication
if (oidc->get_valid_identity()) {
var user => oidc->build_user_from_identity();
}
elsif (request->is_get() && !request->is_ajax()) {
oidc->redirect_to_authorize();
}
else {
Dancer2::Core::Error->new(
status => 401,
message => "You have been logged out. Please try again after refreshing the page.",
template => 'error',
)->throw();
}
API call
To make an API call with propagation of the security context (token exchange) :
# Retrieving a web client (Mojo::UserAgent object)
my $ua = try {
oidc->build_api_useragent('other_app_name')
}
catch {
warning("Unable to exchange token : $_");
Dancer2::Core::Error->new(
status => 403,
message => "Authorization problem. Please try again after refreshing the page.",
template => 'error',
)->throw();
};
# Usual call to the API
my $res = $ua->get($url)->result;
Resource Server
To check an access token from a Resource Server :
my $access_token = try {
return oidc->verify_token();
}
catch {
warning("Token validation : $_");
return;
} or do {
status(401);
return encode_json({error => 'Unauthorized'});
};
unless ($access_token->has_scope($expected_scope)) {
warning("Insufficient scopes");
status(403);
return encode_json({error => 'Forbidden'});
}
# The token is valid and the user has sufficient scopes
To check that the user has an expected role :
my $user = try {
my $access_token = oidc->verify_token();
return oidc->build_user_from_claims($access_token->claims);
}
catch {
warning("Token/User validation : $_");
return;
} or do {
status(401);
return encode_json({error => 'Unauthorized'});
};
unless ($user->has_role($expected_role)) {
warning("Insufficient roles");
status(403);
return encode_json({error => 'Forbidden'});
}
# The token is valid and the user has sufficient roles
SECURITY RECOMMENDATION
It is highly recommended to configure the framework to store session data, including sensitive tokens such as access and refresh tokens, on the backend rather than in client-side cookies. Although cookies can be signed and encrypted, storing tokens in the client exposes them to potential security threats.
AUTHOR
Sébastien Mourlhou
COPYRIGHT AND LICENSE
Copyright (C) Sébastien Mourlhou
This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.