Catalyst-Plugin-OpenIDConnect
view release on metacpan or search on metacpan
IMPLEMENTATION_GUIDE.md view on Meta::CPAN
When the OpenID Connect plugin redirects an unauthenticated user to your login page, it includes a `back` parameter specifying where to return after successful authentication. Your login action **must support the `back` parameter** to resume the auth...
```perl
sub login : Local {
my ( $self, $c ) = @_;
if ( $c->request->method eq 'POST' ) {
my $username = $c->request->params->{username};
my $password = $c->request->params->{password};
# Validate credentials against your user store
if ( validate_user($username, $password) ) {
my $user = get_user($username);
# Store user in session
$c->session->{user} = $user;
$c->session->{user_id} = $user->id;
# IMPORTANT: Redirect to the 'back' parameter if provided
# This resumes the authorization flow after authentication.
# Validate it to prevent open redirect (only allow relative paths).
my $back = $c->request->params->{back} || '/';
$back = '/' unless $back =~ m{^/[^/]};
return $c->response->redirect( $c->uri_for($back) );
}
$c->stash->{error} = 'Invalid credentials';
}
# Display login form
$c->stash->{template} = 'login.html';
}
```
The plugin will redirect to your login page like: `/login?back=/openidconnect/authorize`. After successful authentication, redirect back to the `back` URL to resume the authorization process.
## Security Considerations
BEGIN { extends 'Catalyst::Controller'; }
sub login : Local {
my ( $self, $c ) = @_;
if ( $c->request->method eq 'POST' ) {
my $username = $c->request->params->{username};
my $password = $c->request->params->{password};
# Validate credentials
if ( validate_credentials($username, $password) ) {
my $user = get_user($username);
$c->session->{user} = $user;
# IMPORTANT: Redirect to 'back' parameter to resume OIDC flow
my $back = $c->request->params->{back} || '/';
return $c->response->redirect($back);
}
$c->stash->{error} = 'Invalid credentials';
}
$c->stash->{template} = 'login.html';
}
1;
```
### 5. Use in your controllers
example/app.pl view on Meta::CPAN
Login page/action. In a real app, this would authenticate users.
=cut
sub login : Local {
my ( $self, $c ) = @_;
if ( $c->request->method eq 'POST' ) {
my $username = $c->request->params->{username};
# In a real application, validate credentials here
if ( $username && length($username) > 0 ) {
# Create a mock user object
my $user = _create_mock_user($username);
$c->session->{user_id} = $user->{id};
$c->session->{user} = $user;
# IMPORTANT: The 'back' parameter is used by the OpenID Connect plugin
# to resume the authorization flow after successful authentication.
# Always redirect to it if provided to properly complete the OIDC flow.
lib/Catalyst/Plugin/OpenIDConnect/Controller/Root.pm view on Meta::CPAN
$c->log->warn("PKCE code_verifier missing for client: $client_id");
return $self->_json_error( $c, 'invalid_grant', 'code_verifier is required' );
}
unless ( _verify_pkce( $code_verifier, $code_data->{code_challenge} ) ) {
$c->log->warn("PKCE verification failed for client: $client_id");
return $self->_json_error( $c, 'invalid_grant', 'code_verifier is invalid' );
}
$c->log->debug('PKCE verification passed') if $config->{debug};
}
# If client_secret is provided, verify client credentials (confidential client)
if ($client_secret) {
$c->log->debug("Verifying client credentials for: $client_id") if $config->{debug};
my $client = $c->openidconnect->get_client($client_id);
unless ( $client && slow_eq( $client->{client_secret}, $client_secret ) ) {
$c->log->warn("Client authentication failed for: $client_id");
return $self->_json_error( $c, 'invalid_client', 'Client authentication failed' );
}
} else {
# For public clients (no secret provided), at least verify client exists
my $client = $c->openidconnect->get_client($client_id);
unless ($client) {
$c->log->warn("Unknown client: $client_id");
( run in 0.915 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )