How to Build an Authentication API with JWT Token in Perl
Hi, In many web applications, user authentication is a critical feature that allows users to securely log in and access their data. One common approach to implementing authentication is to use JSON Web Tokens (JWT), which are a type of token-based authentication that can be used across multiple domains and platforms.
In this tutorial, we will show you how to build an authentication API with JWT token in Perl. We will be using the Mojolicious web framework, which is a powerful and flexible framework that makes it easy to build web applications in Perl.
Step 1: Install Dependencies
To get started, you'll need to install the following Perl modules:
Mojolicious
Mojolicious::Plugin::JWT
You can install these modules using the 'cpanm' command:
$ cpanm Mojolicious Mojolicious::Plugin::JWT
use Mojolicious::Lite;
use Mojolicious::Plugin::JWT;
# set up JWT plugin
plugin 'JWT';
# login endpoint
post '/login' => sub {
my $c = shift;
# get username and password from request body
my $username = $c->req->json->{username};
my $password = $c->req->json->{password};
# TODO: validate username and password
# generate JWT token
my $jwt = $c->jwt_encode({username => $username});
# return JWT token in response body
$c->render(json => {token => $jwt});
};
app->start;
$ curl -X POST -H "Content-Type: application/json" -d '{"username": "myusername", "password": "mypassword"}' http://localhost:3000/login{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im15dXNlcm5hbWUifQ.eyBtLXVzZXJuYW1l"}
#!/usr/bin/env perl#########################################################SCRIPT: UserManagement.pl#AUTHOR: Kaavannan Karuppaiyah#DATE RELEASED: 11-03-2023#Description:#Rest Apis Written in Perl,it is used to create user#For Login,Signup,AdminAddUser,List Users Functions are#Added with Mysql Database, Loggers and Validations Also#Added to the Code, Enjoy to OpenSource########################################################use Mojolicious::Lite;use Mojo::JSON qw(encode_json decode_json);use Mojo::JWT;use DBI;use Log::Log4perl;use Try::Tiny;#use Crypt::Eksblowfish::Bcrypt;# Logger configurationLog::Log4perl->init(\<<'CONF');log4perl.logger = DEBUG, Screenlog4perl.appender.Screen = Log::Log4perl::Appender::Screenlog4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayoutlog4perl.appender.Screen.layout.ConversionPattern = [%d{ISO8601}] [%p] %m%nCONFmy $logger = Log::Log4perl->get_logger();# Database configurationmy $db_name = 'w3esource';my $db_user = 'root';my $db_pass = 'root';my $db_host = 'localhost';my $db_port = 3306;my $dbh;# Attempt to connect to databaseeval {$dbh = DBI->connect("dbi:mysql:$db_name:$db_host:$db_port", $db_user, $db_pass, { RaiseError => 1 });};if ($@) {$logger->error("Couldn't connect to database: $@");die "Couldn't connect to database: $@";}# User classpackage User {use strict;use warnings;sub new {my $class = shift;my $self = {username => shift,password => shift,email => shift,};bless $self, $class;return $self;}sub username {my $self = shift;return $self->{username};}sub password {my $self = shift;return $self->{password};}sub email {my $self = shift;return $self->{email};}}sub is_email {my ($email) = @_;return $email =~ /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i;}sub password_hash {my ($password, $algorithm) = @_;my $cost = 10; # Replace with the desired cost factormy $hash;my $salt = '';$salt .= chr(int(rand(256))) for 1..16;if ($algorithm eq 'PASSWORD_BCRYPT') {$hash = Crypt::Eksblowfish::Bcrypt::bcrypt_hash({key_nul => 1,cost => $cost,salt => $salt,}, $password);}return $hash;}# User routesget '/user' => sub {my $c = shift;if ($c->req->method eq 'POST') {# Handle POST request to create new usermy $json = $c->req->json;#die "Invalid input: missing username, password, or email" unless $json->{username} and $json->{password} and $json->{email};if (!defined $json->{username} || !defined $json->{password} || !defined $json->{email}) {$c->render(json => { success => 0, message => 'Missing username, password, or email' }, status => 400);return;}if (length($json->{username}) < 4 || length($json->{password}) < 8 || !is_email($json->{email})) {$c->render(json => { success => 0, message => 'Invalid username, password, or email' }, status => 400);return;}my $stmt = $dbh->prepare('INSERT INTO user (username, password, email) VALUES (?, ?, ?)');my $rv = try { $stmt->execute($json->{username}, $json->{password}, $json->{email}) } catch { $logger->warn("Failed to execute statement: $_"); undef };#my $rv = $stmt->execute($json->{username}, $json->{password}, $json->{email});if(defined $rv) {$c->render(json => { success => 1 });} else {$c->render(json => { success => 0, message => 'Failed to add user' });}} elsif ($c->req->method eq 'GET') {#$logger->debug("GET CALL");$logger->info("GET request received");# Handle GET request to retrieve user datamy $stmt = $dbh->prepare('SELECT * FROM user');my $rv = try { $stmt->execute() } catch { $logger->warn("Failed to execute statement: $_"); undef };my @rows;while (my $row = $stmt->fetchrow_hashref) {my $jwt = Mojo::JWT->new(secret => 'my_secret_key')->claims({ username => $row->{username}, email => $row->{email} })->encode;push @rows, { username => $row->{username}, email => $row->{email}, token => $jwt };}$c->render(json => { success => 1, data => \@rows });} else {# Handle unsupported HTTP methods$c->render(json => { success => 0, message => 'Unsupported HTTP method' }, status => 405);}};post '/admin/adduser' => sub {my $c = shift;my $json = $c->req->json;#my $user = User->new($json->{username}, $json->{password}, $json->{email});unless (defined $json->{username} && defined $json->{password} && defined $json->{email}){$c->render(json => { success => 0, message => 'Missing username, password, or email' }, status => 400);return;}unless (length($json->{username}) >= 4 && length($json->{password}) >= 8 && is_email($json->{email})) {$c->render(json => { success => 0, message => 'Invalid username, password, or email' }, status => 400);return;}# Check if user already existsmy $existing_user = $dbh->selectrow_hashref('SELECT * FROM user WHERE username = ?', undef, $json->{username});if (defined $existing_user) {$c->render(json => { success => 0, message => 'Username already exists' }, status => 409);return;}## Hash password#my $password_hash = password_hash($json->{password}, 'PASSWORD_BCRYPT');my $stmt = $dbh->prepare('INSERT INTO user (username, password, email) VALUES (?, ?, ?)');my $rv = try { $stmt->execute($json->{username}, $json->{password}, $json->{email}) } catch { $logger->warn("Failed to execute statement: $_"); undef };if (defined $rv) {$c->render(json => { success => 1 });} else {$c->render(json => { success => 0, message => 'Failed to add user' });}};# Login routepost '/login' => sub {my $c = shift;my $json = $c->req->json;unless (defined $json->{username} && defined $json->{password}) {$c->render(json => { success => 0, message => 'Missing username or password' }, status => 400);return;}my $stmt = $dbh->prepare('SELECT * FROM user WHERE username = ? AND password = ?');my $rv = try {$stmt->execute($json->{username}, $json->{password});} catch {$logger->warn("Failed to execute database query: $stmt");};#my $rv = try { $stmt->execute($json->{username}, $json->{password}) } catch {$logger->warn("Failed to execute database query: $stmt");};if ($rv and my $row = $stmt->fetchrow_hashref) {my $jwt = Mojo::JWT->new(secret => 'my_secret_key')->claims({ username => $row->{username}, email => $row->{email} })->encode;$c->render(json => { success => 1, token => $jwt });$logger->info("User logged in: $json->{username}");} else {$c->render(json => { success => 0, message => 'Invalid username or password' });}};# Signup routepost '/signup' => sub {my $c = shift;my $json = $c->req->json;# Validate request bodyunless (defined $json->{username} && defined $json->{password} && defined $json->{email}) {$c->render(json => { success => 0, message => 'Missing required fields' });$c->app->log->warn("Missing required fields in request body: " . $c->req->body);return;}# Check if user already existsmy $check_stmt = $dbh->prepare('SELECT * FROM user WHERE username = ? OR email = ?');my $check_rv = $check_stmt->execute($json->{username}, $json->{email});if ($check_rv and my $row = $check_stmt->fetchrow_hashref) {$c->render(json => { success => 0, message => 'Username or email already taken' });$c->app->log->warn("Username or email already taken: " . $json->{username} . " " . $json->{email});return;}my $stmt = $dbh->prepare('INSERT INTO user (username, password, email) VALUES (?, ?, ?)');my $rv = $stmt->execute($json->{username}, $json->{password}, $json->{email});if ($rv) {my $jwt = Mojo::JWT->new(secret => 'my_secret_key')->claims({ username => $json->{username}, email => $json->{email} })->encode;$c->render(json => { success => 1, token => $jwt });$c->app->log->info("User added successfully: " . $json->{username} . " " . $json->{email});} else {$c->render(json => { success => 0, message => 'Failed to add user' });$c->app->log->error("Failed to add user to database: " . $json->{username} . " " . $json->{email});}};app->start;
Labels: How to Build an Authentication API with JWT Token in Perl, how to generate jwt token, jwt authentication example, jwt token authentication web api
0 Comments:
Post a Comment
Note: only a member of this blog may post a comment.
<< Home