REST API Endpoint Authentication
The nuxt-saasmvp-oauth
module can be used for either or both User and REST API Endpoint authentication. REST API Endpoint authentication is implemented using client functions, server middleware and associated Authorization Server REST API endpoints.
READ THIS FIRST
Be sure to review the steps required to initialize the nuxt-saasmvp-oauth
module before proceeding.
Client Functions
smvpGetOAuthApiKey
Thenuxt-saasmvp-oauth
module provides the smvpGetOAuthApiKey
client function that sends an Implicit Authorization Grant to the Authorization Server REST API Endpoint smvp-api-token.post.ts
. The smvp-api-token.post.ts
REST API Endpoint returns a JWT Access Token and Status code to smvpGetOAuthApiKey
in a JSON object. If a JWT Access Token has been successfully generated by the Authorization Server, the JWT Access Token will be returned to smvpGetOAuthApiKey
with the HTTP status code 200, otherwise the JWT Access Token returned will be NULL and the HTTP status code 400. The lifetime of the JWT Access Token is hardcoded to be valid for ten years and is attached to the Authorization Grant claim acctNum:string
The JWT Access Token can be used as a Bearer Token in the authentication of Developer defined REST API Endpoints.
Type
smvpGetOAuthApiKey(acctNum:string):Promise<string>
Parameters
- Parameter: acctNum
- Type: String Array, required
- Description: The acctNum claim for the Implicit Authorization Grant. Binds an Account Number or other unique identifier to the JWT Access Token for use as a Bearer Token in a Developer defined REST API Endpoint.
Examples
<script setup>
const apiKey = ref();
const genApiKey = async () => {
const acctNum = "1111";
apiKey.value = await smvpGetOAuthApiKey(acctNum);
};
</script>
Server Functions
smvpIsRestAuth
The smvpIsRestAuth
Server function returns TRUE if the developer defined API REST Endpoint JWT Access Token (Bearer Token) has been authenticated by the smvp-apiauth.ts
middlewware, otherwise FALSE if token is invalid.
Type
smvpIsRestAuth(void):boolean
Parameters
None
Examples
TIP
Use the following template when writing your REST API Server Endpoints
export default defineEventHandler((event) => {
if (!smvpIsRestAuth()) {
event.node.res.statusCode = 401
return {
message: 'Unauthorized',
status: 401,
data: {},
}
}
//
// Developer REST API Endpoint code goes here
//
//normal return example
event.node.res.statusCode = 200
return {
message: 'Success',
status: 200,
data: {}
}
})
Developer Defined REST API Endpoints
When defining your own REST API Endpoints, you can refer both to the nuxt-saasmvp-oauth
module playground for a reference implementation and the official NUXT 3 Server REST API Examples. You may also want to refer to the Stack Overflow blog post entitled Best Practices for REST API Design.
X-TOKEN Header
The JWT Access Token (i.e. Bearer Token) must be in the X-TOKEN HTTP(S) Header which is subsequently authenticated by the smvp-apiauth.ts
server middleware BEFORE the developer defined REST API Endpoint is reached. The REST API Endpoint will use the smvpIsRestAuth
server function to determine if the request will be honored by the REST API Endpoint or a 401 Unauthorized
HTTP status will be sent back to the requestor. When calling your REST API Endpoints from the client, refer to the following examples:
GET HTTP Method Client Example
In the GET HTTP method example, there is no body sent in the HTTP(S) request to the developer defined REST API Endpoint. While there are several libraries available to help the developer with messaging REST API Endpoints, this example uses the JavaScript fetch
API.
const getMethod = async (jwtToken:string) => {
try {
const response = await fetch("/api/v1/apitest",
{ method: "GET",
headers : {
"Content-Type": "application/json",
"X-TOKEN": jwtToken,
},
})
const json = await response.json();
console.log(json)
//any further processing
} catch (error) {
console.log(error);
//process error
}//end of try-catch block
//any further processing
};
POST, PUT, PATCH, DELETE HTTP Method Client Example
In the POST, PUT, PATCH, and DELETE HTTP method example, a body is sent in the HTTP(S) request to the developer defined REST API Endpoint. While there are several libraries available to help the developer with messaging REST API Endpoints, this example uses the JavaScript fetch
API.
const otherMethods = async (jwtToken:string) => {
const jsonBody = {"string": "text", "number": 1} //any json object
const body = Object.assign({}, jsonBody);
try {
const response = await fetch("/api/v1/apitest",
{ method: "POST", // or 'PUT' or 'PATCH' or 'DELETE'
headers : {
"Content-Type": "application/json",
"X-TOKEN": jwtToken,
},
body: JSON.stringify(body),
})
const json = await response.json();
console.log(json)
//any further processing
} catch (error) {
console.log(error);
//process error
}//end of try-catch block
//any further processing
};
Server Middleware
smvp-apiauth.ts
The nuxt-saasmvp-oauth
module uses the smvp-apiauth.ts
server middleware which is installed when Nuxt loads the nuxt-saasmvp-oauth
module. The smvp-apiauth.ts
server middleware handler will run on every HTTP request before any other server route to determine if the developer defined REST API Endpoint is protected and needs to be authenticated using the JWT Access Token (i.e. Bearer Token) provided in the REST API Endpoint X-TOKEN header of the HTTP request.
Defining Protected REST API Routes
The nuxt-saasmvp-oauth
module expects developer defined REST API Endpoints to adhere to the following directory tree structure inside of the NUXT 3 application. NUXT 3 expects that all APIs will be located in the ./server/api
directory. The nuxt-saasmvp-oauth
module goes a step further by enforcing a version directory ./server/api/v1, ./server/api/v2 ... ./server/api/v99
in order to provide a best practice for versioning REST APIs and more importantly for determing if a REST API route should be protected by the nuxt-saasmvp-oauth
server middleware.
The most important step in configuring the nuxt-saasmvp-oauth
module's Authorization Server is to make sure you provide a smvp.oauth.json
file in your application's ./server
directory. The smvp.oauth.json
file is read by the smvpServerInit.ts
Authorization Server function when the nuxt-saasmvp-oauth
module starts. The smvp.oauth.json
file configures the nuxt-saasmvp-oauth
module for both User and REST API Authentication.
REST API Directory Tree Structure
.
├── server
│ │ ├── smvp.oauth.json
│ ├── api
│ │ ├── v1
│ │ │ ├── api.get.ts
│ │ │ ├── api.post.ts
│ │ │ ├── api.put.ts
│ │ │ ├── api.patch.ts
│ │ │ ├── api.delete.ts
│ │ └── v99
│ │ ├── api.get.ts
│ │ ├── api.post.ts
│ │ ├── api.put.ts
│ │ ├── api.patch.ts
│ │ └── api.delete.ts
The smvp.oauth.json protected
object
protected
objectThe smvp.oauth.json
file contains a protected
json object that holds an array of strings. Each string in the protected
json object specifies a REST API route that is to be authenticated by the nuxt-saasmvp-oauth
module's smvp-apiauth.ts
server middleware. There are two types of routes that can be protected, a strict
route and a wildcard
route. If a route is not included in the smvp.oauth.json
file protected
json object, the route is not authenticated. Don't leave out the protected
json object. If no routes need to be protected, you can simply specify the protected
json object with an empty array (i.e. [])
TIP
The nuxt-saasmvp-oauth
module playground has examples of both static
and wildcard
REST API Endpoints for your review.
Strict Routes
A strict
route requires an exact match of the REST API route path name for developer REST API Endpoint authentication to succeed. An example of a strict
route looks like /api/v1/apitest
.
Wildcard Routes
A wildcard
route allows for a REST API route path name to contain a variable number of additional nested paths, dynamic parameters or query parameters that need to be supplied to a developer defined REST API Endpoint. A wildcard
on a protected
json object appends /*
to a static route. An example of a wildcard
route appears as /api/v1/apitest/*
.
Dynamic Parameter with Nested Path REST API Example
The developer defined nested path REST API /api/v1/apitest/[id]/balance
Endpoint passes validation when specifying a protected
json object entry of /api/vi/apitest/*
. If a strict
entry of /api/v1/apitest
is used, the smvp-apiauth.ts
server middleware will fail validation and FALSE will be returned when calling the smvpServerRestAuth
function in the developer defined REST API Endpoint. See Nuxt Route Parameters for more information on the use of dynamic parameters in REST API Endpoints.
Query Parameter REST API Example
The developer defined query parameter REST API /api/v1/apitest?lastname=Smith&age=30
Endpoint passes validation when specifying a protected
json object entry of /api/vi/apitest/*
. If a strict
entry of /api/v1/apitest
is used, the smvp-apiauth.ts
server middleware will fail validation and FALSE will be returned when calling the smvpServerRestAuth
function in the developer defined REST API Endpoint. See Nuxt Query Parameters for more information on the use of query parameters in REST API Endpoints.
Authorization Server REST API
The nuxt-saasmvp-oauth
module contains an Authorization Server that has an additional REST API Endpoint, smvp-api-token.post.ts
which is used to issue JWT Access Tokens for use in a Developer defined REST API Endpoint.
smvp-api-token.post.ts
The nuxt-saasmvp-oauth
module smvpGetOAuthApiKey
client function sends an Implicit Authentication Grant request to the Authorization Server smvp-api-token.post.ts
REST API Endpoint to get a JWT Access Token. The Developer should never message this REST API Endpoint directly and is shown for educational purposes only.
JSON Implicit Authorization Grant Request
{
"iss": "saasmvp",
"sub": "api-token",
"jti": null,
"acctno": "1111",
"ts": 1704414495
}
Parameters
- Parameter: iss
- Type: String, required, read-only
- Description: JWT issuer claim. Hardcoded by the `smvpGetOAuthApiKey` client function.
- Parameter: sub
- Type: String, required, read-only
- Description: JWT subject claim. Hardcoded by the `smvpGetOAuthApiKey` client function.
- Parameter: jti
- Type: String, required, read-only
- Description: JWT ID. Reserved for future use. Hardcoded by the `smvpGetOAuthApiKey` client function.
- Parameter: acctNum
- Type: String, required
- Description: The acctNum claim for the Implicit Authorization Grant. Binds an Account Number or other unique identifier to the JWT Access Token. A parameter supplied to the `smvpGetOAuthApiKey` client function by the Developer.
- Parameter: ts
- Type: Number, required
- Description: The current Unix Epoch time for the Implicit Authorization Grant. Hardcoded by the smvpGetOAuthApiKey` client function.
cURL Example
curl --location 'http://localhost:3000/api/smvp/smvp-api-token' \
--header 'Content-Type: application/json' \
--data '{
"iss": "saasmvp",
"sub": "api-token",
"jti": null,
"acctno": "1111",
"ts": 1704414495
}'
Valid JSON Response
{
"message": "JWT API Token Generated",
"status": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzYWFzbXZwIiwic3ViIjoiYXBpLXRva2VuIiwianRpIjpudWxsLCJhY2N0bm8iOiIxMTExIiwidHMiOjE3MTYzMzk3MzQsImlhdCI6MTcxNjMzOTczNCwiZXhwIjoyMDMxOTE1NzM0fQ.jb8aTP92UQSV4-LukKCOf06PTXC5DMcWXG2t50vZLZk"
}
}
Error JSON Response
{
"message": "JWT API Token Not Generated",
"status": 400,
"data": {
"token": null
}
}