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 )