Friday 11 December 2020

Perl - securing web services using OAuth 2.0


Hi, This program is a simple OAuth 2.0 authentication and authorization implementation using the Mojolicious web framework in Perl. It allows a user to log in and authorize a client application to access protected resources.

The program defines the necessary endpoints for authentication and authorization using the get method from the Mojolicious::Lite module. The $auth_endpoint and $token_endpoint variables define the authentication and token endpoints for the OAuth 2.0 provider. The $client_id, $client_secret, $redirect_uri, and $scope variables define the client credentials and scope for the OAuth 2.0 client.


The /api/login endpoint is used to initiate the OAuth 2.0 authentication flow. When a user navigates to this endpoint, the program redirects them to the OAuth 2.0 provider's authentication endpoint with the appropriate query parameters.

The /callback endpoint is used to handle the response from the OAuth 2.0 provider after the user has authorized the client application. The program retrieves the authorization code and state from the query parameters and sends a POST request to the token endpoint with the appropriate parameters to obtain an access token. The access token is then decoded and verified using the JWT module, and the user's email address is extracted from the token's claims. If the email address is present, it is stored in the user's session and the program redirects the user to the /api/example endpoint, which returns a JSON object containing the user's email address.

Overall, the program provides a simple example of how to implement OAuth 2.0 authentication and authorization using the Mojolicious web framework and Perl.


use Mojolicious::Lite;

use Mojo::UserAgent;

use Mojo::JWT;



# OAuth 2.0

my $ua = Mojo::UserAgent->new;

my $auth_endpoint = 'https://example.com/oauth2/auth';

my $token_endpoint = 'https://example.com/oauth2/token';

my $client_id = 'client_id';

my $client_secret = 'client_secret';

my $redirect_uri = 'https://yourdomain.com/callback';

my $scope = 'openid profile email';



# Authentication

get '/api/login' => sub {

  my $c = shift;

  my $auth_url = $auth_endpoint . '?' . join('&', (

    'client_id=' . $client_id,

    'response_type=code',

    'redirect_uri=' . $redirect_uri,

    'scope=' . $scope,

    'state=' . time()

  ));

  $c->redirect_to($auth_url);

};



# Authorization

get '/callback' => sub {

  my $c = shift;

  my $code = $c->param('code');

  my $state = $c->param('state');

  if (!$code || !$state) {

    $c->render(json => { error => 'Unauthorized' }, status => 401);

    return;

  }

  my $token_res = $ua->post_form($token_endpoint => {

    grant_type => 'authorization_code',

    code => $code,

    redirect_uri => $redirect_uri,

    client_id => $client_id,

    client_secret => $client_secret

  })->result->json;

  if (!$token_res || !$token_res->{access_token}) {

    $c->render(json => { error => 'Unauthorized' }, status => 401);

    return;

  }

  my $jwt = Mojo::JWT->new(secret => $client_secret)->decode($token_res->{access_token});

  my $email = $jwt->claims->{email};

  if (!$email) {

    $c->render(json => { error => 'Unauthorized' }, status => 401);

    return;

  }

  $c->session(email => $email);

  $c->redirect_to('/api/example');

};



# Example API route

get '/api/example' => sub {

  my $c = shift;

  my $email = $c->session('email');

  if (!$email) {

    $c->render(json => { error => 'Forbidden' }, status => 403);

    return;

  }

  $c->render(json => { email => $email });

};



app->start;


Above code uses OAuth 2.0 to authenticate and authorize the user. The get route /api/login redirects the user to the OAuth 2.0 authorization endpoint, where the user can authenticate and authorize the client.

The get route /callback handles the OAuth 2.0 authorization code flow. It first checks if the authorization code and state are present in the URL query parameters. If not, the server returns a 401 Unauthorized error. If they are present, the server sends a POST request to the OAuth 2.0 token endpoint with the authorization code to retrieve the access token. If the access token is not present or valid, the server returns a 401 Unauthorized error. If the access token is valid, the server decodes it using a JWT library and retrieves the user's email address from the JWT claims. If the email address is not present, the server returns a 401 Unauthorized error. If the email address is present, the server stores it in the session and redirects the user to the example API route `/`

The get route /api/example is an example API route that requires authentication. It retrieves the user's email address from the session and returns it in a JSON response. If the email address is not present in the session, the server returns a 403 Forbidden error.

Above code uses OAuth 2.0 to secure the web services by requiring the user to authenticate and authorize the client before accessing the protected resources. The access token is validated using a JWT library, and the user's email address is used as the authentication credential.

Labels:

0 Comments:

Post a Comment

Note: only a member of this blog may post a comment.

<< Home