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

README.md  view on Meta::CPAN


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 )