Browser-OIDC
view release on metacpan or search on metacpan
lib/Browser/OIDC.pm view on Meta::CPAN
my $tiny = HTTP::Tiny->new;
sub new($class, $target_base) {
my $response = $tiny->get("$target_base/.well-known/openid-configuration");
croak "Error: $response->{status}" if $response->{status} != 200;
my $self = decode_json($response->{content});
bless $self, $class;
}
my sub make_target($authorization_endpoint, $redirect_uri, %options) {
my $full_target = URI->new($authorization_endpoint);
$full_target->query_param_append(response_type => 'code');
$full_target->query_param_append(redirect_uri => $redirect_uri);
$full_target->query_param_append(client_id => $options{client_id} // '');
$full_target->query_param_append(client_secret => $options{client_secret} // '');
$full_target->query_param_append(code_challenge => $options{challenge}) if $options{challenge};
$full_target->query_param_append(code_challenge_method => 'S256');
$full_target->query_param_append(scope => join ' ', $options{scope}->@*) if $options{scope};
$full_target->query_param_append(state => $options{state});
return $full_target;
}
sub get_token($self, %options) {
my $state = $options{state} = encode_base64url(random_bytes(16));
my $verifier = encode_base64url(random_bytes(32));
$options{challenge} = encode_base64url(sha256($verifier)) if delete $options{pkce};
my $daemon = HTTP::Daemon->new(LocalAddr => 'localhost');
my $port = $daemon->sockport;
my $redirect_uri = "http://localhost:$port/auth/callback";
my $full_target = make_target($self->{authorization_endpoint}, $redirect_uri, %options);
my $ok = open_browser($full_target->canonical);
while (1) {
my $sock = $daemon->accept;
my $response = $sock->get_request;
if ($response->uri->path eq '/auth/callback') {
my $code = $response->uri->query_param('code');
my $received_state = $response->uri->query_param('state');
if ($received_state ne $state) {
lib/Browser/OIDC.pm view on Meta::CPAN
close $sock;
my %arguments = (
grant_type => 'authorization_code',
redirect_uri => $redirect_uri,
code => $code,
code_verifier => $verifier,
client_id => $options{client_id} // '',
client_secret => $options{client_secret} // '',
);
my $response2 = $tiny->post_form($self->{token_endpoint}, \%arguments);
return decode_json($response2->{content}) if $response2->{status} == 200;
} else {
$sock->send_error(404);
close $sock;
}
}
}
1;
lib/Browser/OIDC.pm view on Meta::CPAN
=head2 new
my $oidc = Browser::OIDC->new($base_url);
This creates a new
=head2 get_token
$oidc->get_token(%options);
This fetches an OIDC token from the endpoint. It takes the following options:
=over 4
=item client_id
The client identifier. Effectively mandatory.
=item client_secret
The client secret, if any.
( run in 0.747 second using v1.01-cache-2.11-cpan-364913b4093 )