authkeys
v0.2.4
Published
🗝️ Create API & Server keys with Permissions and CustomData 🗝️
Downloads
2
Maintainers
Readme
🔑 AuthKeys
Create API & Server keys with Permissions and CustomData
This tool was designed to improve permissions management, especially in HTTP and database tasks that works with url-paths to access to the stored data.
Table of Contents
- 1.1. Creating a Key
- 1.2. Custom Tokens
- 1.3. Updating Secret
- 1.4. Adding CustomData
- 2.1. Local Storage
- 2.2. Cloud Storage
- 3.1. Managing Permissions
- 3.2. Check Permissions
- 4.1. Tokens in Client-Side
- 4.1.1. Query Parameter
- 4.1.2. Body Property
- 4.1.3. Authorization Header
- 4.1. Tokens in Client-Side
1. Getting Started
Let's create our first auth-key, but first, we need to install the package in our current Node.js project.
npm install --save authkeys
1.1. Creating a Key
Is really easy to make a new key to start adding permissions and custom-data (json). Just import the AuthKey class from the package or use the createKey( ) method which uses the same parameters as the class.
const { createKey, AuthKey } = require( "authkeys" ) ;
let key = createKey( ) ;
// or
let key2 = new AuthKey( ) ;
import { createKey, AuthKey } from "authkeys" ;
let key = createKey( ) ;
By default, the class constructor will create a token (sha256 hash) based in a random secret string and also it will add a random 32-length public password (can be useful or not, but I just added it to prevent).
AuthKey {
"token" : "1696be1679f6696dd8e7bca9c7584e4a4916548d883d3e84dad3eec10c866a79" ,
"secret" : "RHJVpx4EQk1drllHmUmHfUShzejcqod0Lc1YLffqUDR6YHKaucPGtQj46TfG0OfU" ,
"public" : "WlagtNpeLnPlJmSuhVZYsNTpLPA3g9lP" ,
"permissions" : { } ,
"data" : { }
} ;
1.2. Custom Tokens
The token is the value used to identify your keys in a database.
In this way, you can use the token to make HTTP calls in a server, obtaining the AuthKey
instance by searching its data in your database using the token as an ID.
The AuthKey
class will generate a random token, but you can set your own secret string to generate it, even select the hash algorithm.
const { createKey, AuthKey } = require( "authkeys" ) ;
// Using a Custom Token-Value [v] ;
let key1 = createKey( "my-custom-token-value" ) ;
// Generating a Token from a Secret-String [v] ;
// You must set algorithm parameter to indicate that you want to generate a token from the first string.
let key2 = createKey( "i-love-pizza", "sha256" ) ;
console.log( key1.token, key2.token ) ;
RSA-MD4
RSA-MD5
RSA-MDC2
RSA-RIPEMD160
RSA-SHA1
RSA-SHA1-2
RSA-SHA224
RSA-SHA256
RSA-SHA3-224
RSA-SHA3-256
RSA-SHA3-384
RSA-SHA3-512
RSA-SHA384
RSA-SHA512
RSA-SHA512/224
RSA-SHA512/256
RSA-SM3
blake2b512
blake2s256
id-rsassa-pkcs1-v1_5-with-sha3-224
id-rsassa-pkcs1-v1_5-with-sha3-256
id-rsassa-pkcs1-v1_5-with-sha3-384
id-rsassa-pkcs1-v1_5-with-sha3-512
md4
md4WithRSAEncryption
md5
md5-sha1
md5WithRSAEncryption
mdc2
mdc2WithRSA
ripemd
ripemd160
ripemd160WithRSA
rmd160
sha1
sha1WithRSAEncryption
sha224
sha224WithRSAEncryption
sha256
sha256WithRSAEncryption
sha3-224
sha3-256
sha3-384
sha3-512
sha384
sha384WithRSAEncryption
sha512
sha512-224
sha512-224WithRSAEncryption
sha512-256
sha512-256WithRSAEncryption
sha512WithRSAEncryption
shake128
shake256
sm3
sm3WithRSAEncryption
ssl3-md5
ssl3-sha1
whirlpool
1.3. Updating Secret
Maybe you want to reset your users' API keys without deleting permissions, so you can change the secret
property and then call updateToken( )
.
About the public
password property, just change it like any other variable.
const { AuthKey } = require( "authkeys" ) ;
let key = new AuthKey( "love-lemon-flavor", "sha256" ) ;
key.secret = "new-secret" ;
const newToken = key.updateToken( ) ;
// Update the token with a new algorithm [v] ;
const newMD5Token = key.updateToken( "md5" ) ;
// Public-Password doesn't need to call updateToken( ) method.
// Remember, tokens is just based on secret property.
key.public = "new-public-password" ;
1.4. Adding CustomData
CustomData is just a little feature to store simple data (strings, numbers, booleans or even objects) in our keys.
// SET [v] ;
key.data( "key", "value" ) ;
key.data( "pizza", true ) ;
// GET [v] ;
var wantPizza = key.data( "pizza" ) ;
2. Saving & Loading Keys
2.1. Local Storage
Save your current key data (hexadecimal) in your drive and then load it with all its permissions and custom-data.
const { createKey } = require( "authkeys" ) ;
let key = createKey( ) ;
key.save( "./api.key" ) ;
const { AuthKey, loadKey } = require( "authkeys" ) ;
let key = AuthKey.load( "./api.key" ) ;
// or
let key = loadKey( "./api.key" ) ;
2.2. Cloud Storage
Sometimes we will need to save the key in a cloud-storage or database, so we can get a JSON and then parse it into a new AuthKey.
let obj = key.toJSON( ) ;
const { AuthKey, parseKey } = require( "authkeys" ) ;
let key = AuthKey.parse( obj ) ;
// or
let key = parseKey( obj ) ;
3. Permissions
Permissions are a bit more difficult, that's why we set it aside in a separate section. You just need to understand that permissions work based on url-paths or IDs.
Note: The AuthKey permissions structure are useful for HTTP servers, but they aren't exclusive for that.
3.1. Managing Permissions
You can set multiple permissions using url-patterns with permission( pattern<string>, permissions-action<string> )
method.
Just add +
or -
symbol at the beginning of the string and then add the first letter of each type of permission.
r = read
w = write
d = delete
x = execute
key.permission( "id1", "+wr" ) ;
key.permission( "/users/*", "+r" ) ;
key.permission( "id1", "-w" ) ;
key.permission( "/users/*", "-d" ) ;
Note: What happens if I type a letter twice or enter an initial that is not available? Actually nothing, it will be ignored.
:::tip
If you will use AuthKeys with Express.js, don't forget to add a slash (/
) at the beginning of the permissions url-pattern. On this way, you can check permissions using req.path
property.
:::
3.2. Check Permissions
It's really easy to check all available permissions (even those that have not been added), just remove the symbol (+/-) from the string and use only one permission type.
Also you can use checkPermissions(pattern<string>)
method instead to return all permissions in an object.
const canRead = key.permission( "id1", "r" ) ;
const canWrite = key.permission( "/users/blitzcrank", "w" ) ;
const canDelete = key.permission( "/a/pattern/that/does/not/coincide", "r" ) ; // <= It will return false instead an error.
const canExecute = key.permission( "id1", "rw" ) ; // <= Not allowed.
// This method will return all permissions (added or not) in an object.
if( key.checkPermissions( "users/blitzcrank" ).read === true ) {
// do something...
}
4. Express Integration
The AuthKey
middleware will allow you to have a direct access to the permissions of all your keys and their data in every HTTP call in your Express.js server,
using an optional cache system to save time and resources.
See: How middlewares works in Express.js
import { middleware as authkeys, loadKey, createKey } from "authkeys" ;
const { loadKey, createKey } = require( "authkeys" ) ;
const authkeys = require( "authkeys" ).middleware ;
const express = require( 'express' ) ;
const app = express( ) ;
const port = 3000 ;
const fs = require( "fs" ) ;
// Creating a Local-Key for Test [v] ;
let authKey = createKey( ) ;
authKey.permission( "/API/*", "+rw" ) ;
const keysPath = "./keys/" ;
if( !fs.existsSync( keysPath ) ) { fs.mkdirSync( keysPath ) ; }
authKey.save( "./keys/test.key" ) ;
// CONFIGURE MIDDLEWARE [v] ;
const ENABLE_CACHE_KEYS = true ;
const AUTH_KEYS_GET = function( token ) {
/* [!] How auth-keys will be loaded or requested.
// In this example we will get keys from a folder in the server-root.
// You can load keys from a database like Firestore from Firebase.
// Just remember to return the result ;
// ---------------------------------- ; */
let key = null ;
keyFiles = fs.readdirSync( keysPath ) ;
keyFiles.forEach( file => {
if( key ) { return false ; }
// load and check [v] ;
var k = loadKey( keysPath + file ) ;
if( k.token === token ) { return key = k ; }
} ) ;
// If key == null, a 400 response will be returned.
// The result can be a parsable object or an AuthKey instance.
return key ;
} ;
/* Check Keys only in any url under /API/ path. */
app.use( "/API/*", authkeys( AUTH_KEYS_GET, ENABLE_CACHE_KEYS ) ) ;
app.get( '/API/users', (req, res) => {
// Checking Permissions
const auth = req.authKey ; /* <= AuthKey instance. */
const list = req.permissions ; /* <= All permissions for the current URL. */
return res.send( list ) ;
} ) ;
app.listen( port, ( ) => {
console.log( `Example app listening at http://localhost:${port}` ) ;
console.log( "TOKEN => " + authKey.token ) ;
} ) ;
/* Go to http://localhost:3000/API/users?token=${ token-value } */
4.1. Tokens in Client-Side
You can set the token in your HTTP requests in 3 different ways: Query Parameter, Body Property and Authorization Header. The middleware will automatically search all this parameters (in the previous order) in every request.
4.1.1. Query Parameter
Just add the token
query parameter to the URL.
curl http://localhost:3000/API/users?token=TOKEN_VALUE
4.1.2. Body Property
Add the token
property to your body-data.
curl --header "Content-Type: application/json" \
--request POST \
--data '{"token":"TOKEN_VALUE"}' \
http://localhost:3000/API/users
4.1.3. Authorization Header
curl http://localhost:3000/API/users
-H "Authorization: {TOKEN_VALUE}"
5. Full API Documentation
To see full API documentation please visit the github repository.