The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use Mojo::Base -strict;
get '/securitytest' => sub {
my $c = shift->openapi->valid_input or return;
$c->render(openapi => {message => "ok"}, status => 200);
},
'securitytest';
plugin OpenAPI => {
security => {
api_key => sub {
my ($self, $definition, $scopes, $cb) = @_;
my $apikey = $self->req->headers->header('apikey');
my $apiuser = $self->req->headers->header('apiuser');
return $self->$cb("apikey/apiuser missing") unless $apikey and $apiuser;
if ($apikey eq "authenticated" and $apiuser eq "authenticated") {
$self->stash(status => 403);
return $self->$cb("Permission denied");
}
if ($apikey eq "authorized" and $apiuser eq "authorized") {
return $self->$cb();
}
return $self->$cb("Unauthorized");
},
},
};
my $t = Test::Mojo->new;
$t->get_ok('/api/securitytest' => {apikey => 'authorized', apiuser => 'authorized'})
->status_is(200);
$t->get_ok('/api/securitytest' => {apikey => 'authenticated', apiuser => 'authenticated'})
->status_is(403);
$t->get_ok('/api/securitytest' => {apikey => 'unknown', apiuser => 'unknown'})->status_is(401);
$t->get_ok('/api/securitytest')->status_is(401);
done_testing;
__DATA__
@@ sec.yaml
openapi: 3.0.2
info:
title: CSApi
version: "1.0"
description: API test
servers:
- url: /api
security:
- api_key: []
api_user: []
paths:
/securitytest:
get:
x-mojo-name: securitytest
summary: test security
description: >
Will grant authenticated and authorized apikeys access
responses:
200:
$ref: "#/components/responses/200_OK_message"
403:
$ref: "#/components/responses/403_Forbidden"
components:
securitySchemes:
api_key:
type: apiKey
description: API key to authorize requests.
name: apikey
in: header
api_user:
type: apiKey
description: Username going with that key.
name: apiuser
in: header
schemas:
Error:
type: object
required:
- errors
properties:
errors:
type: array
items:
type: object
required:
- message
properties:
message:
type: string
path:
type: string
responses:
200_OK_message:
description: OK
content:
application/json:
schema:
type: object
required:
- message
properties:
message:
type: string
path:
type: string
403_Forbidden:
description: Insufficient priviliges
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
DefaultResponse:
description: Default Response
content:
application/json:
schema:
$ref: "#/components/schemas/Error"