Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@koopjs/auth-direct-file

Package Overview
Dependencies
Maintainers
7
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@koopjs/auth-direct-file - npm Package Compare versions

Comparing version 3.0.0-alpha.0 to 3.0.0

11

CHANGELOG.md

@@ -5,2 +5,13 @@ # Change Log

## 3.0.0
### Changed
* eliminate authenticationSpecification method
### Added
* allow authenticate method to "refresh" a token
* allow token to arrive on header, query, body
### Fixed
* strip 'Bearer ' string from any authorization header
## 2.0.3

@@ -7,0 +18,0 @@ ### Fixed

2

package.json
{
"name": "@koopjs/auth-direct-file",
"version": "3.0.0-alpha.0",
"version": "3.0.0",
"description": "Module for implementing a direct authentication pattern with file-based user-store in Koop",

@@ -5,0 +5,0 @@ "main": "src/index.js",

@@ -5,34 +5,47 @@ # Koop-Auth-Direct-File

[![npm][npm-image]][npm-url]
[![travis][travis-image]][travis-url]
[![Greenkeeper badge][greenkeeper-image]][greenkeeper-url]
## Authentication pattern
## Usage
The authentication module implemented here uses a *direct authentication* pattern; it receives user credentials (username/password) from a client and authenticates those credentials against an identity/user-store. Requests with valid credentials are issued an access-token (a string of encoded-data); The access token is encoded with the use of a secret known only to the Koop server. The access-token expires and becomes invalid after a certain period (default of 60 minutes).
To use this plugin, you need to create a JSON file store. This should be an array of objects with properties `username` and `password`. See [user-store.json.example](user-store.json.example) as an example. Note, that this is a terrible way to store credentials! This plugin is really just meant as an example of how to design a Koop authorization plugin and not meant for any production environment.
![get access token](https://gist.githubusercontent.com/rgwozdz/e44f3686abe40360532fbcc6dccf225d/raw/9768df32fc62e99ce7383c124cab8efdf45b1e18/koop-direct-auth-access-token.png)
This module exports an initialization function that must be supplied with a secret-key and the path to the file that is the user-store. It will return a plugin object that can be registered with Koop.
The issued access-token should be attached to all subsequent service requests by the client. When the server receives a request, it will check for the presence of an access-token and reject any requests that are missing such token. If the token is present, the server attempts to decode it with its stored secret. Failure to decode results in a request rejection. Once decoded, the server checks the token's expiration-date and rejects any token with a date that is out of range. If the token is not expired, the request for the desired resource proceeds.
```javascript
const authPlugin = require('@koopjs/auth-direct-file')('your-secret-key', `path/to/user-store.json`, { tokenExpirationMinutes: 300 })
koop.register(auth)
```
![enter image description here](https://gist.githubusercontent.com/rgwozdz/e44f3686abe40360532fbcc6dccf225d/raw/9768df32fc62e99ce7383c124cab8efdf45b1e18/koop-direct-auth-resources.png)
### Registration order
## Example of Koop authentication implementation
For an auth-plugin to secure the data served by a provider, it must be registered _before_ the provider. Any providers registered _after_ the auth-plugin will not have the plugin's authorization code applied.
The [server.js](./server.js) file provides an example of securing a provider's resources. Start by requiring the authentication module. Pass it a secret and the file path of your user-store.
```javascript
const Koop = require('@koopjs/koop-core');
const providerOne = require('koop-provider-one');
const providerTwo = require('koop-provider-two');
const authPlugin = require('@koopjs/auth-direct-file')('your-secret-key', `path/to/user-store.json`);
let auth = require('@koopjs/auth-direct-file')('pass-in-your-secret', `${__dirname}/user-store.json`)
koop.register(auth)
const koop = new Koop();
Then require and register your providers.
// providerOne, registered before auth-plugin, will be secured by auth-plugin methods
koop.register(providerOne);
koop.register(authPlugin);
// providerTwo, registered after auth-plugin, will NOT be secured
koop.register(providerTwo);
const provider = require('./')
koop.register(provider)
```
The authentication module will configure and add its `authorize`, `authenticate`, and `authenticationSpecification` functions to the provider's model prototype. Output services will leverage these functions to secure the service endpoints and properly route requests to authenticate.
The underlying reason that order matter is because an auth-plugin add its `authorize` and `authenticate` functions to all _registered_ providers. (Note that providers may implement their own `authorize` and `authenticate` prototype methods, and if they do these will be used preferentially.) Output services will leverage these functions to secure the service endpoints and properly route requests to authenticate.
Finally, create a JSON file store. This should be an array of objects with properties `username` and `password`. Set an environment variable `USER_STORE` with the path of the file relative to the root of the repository (e.g, `USER_STORE=./user-store.json`)
## Authentication API
## API
### (secret, options) ⇒ <code>Object</code>
### Module initialization function
`(secret, userStoreFilePath, options) ⇒ Object`
* configure the authentication module with secret use for token encoding/decoding

@@ -46,60 +59,25 @@

| options.tokenExpirationMinutes | <code>integer</code> | minutes until token expires (default 60) |
| options.useHttp | <code>boolean</code> | pass the `useHttp` boolean flag as part of the authenticationSpecification function result|
## Special considerations for use with [koop-output-geoservices](https://github.com/koopjs/koop-output-geoservices)
[koop-output-geoservices](https://github.com/koopjs/koop-output-geoservices) assumes that token-services occur over HTTPS. For development purposes you may wish to allow authentication to occur of HTTP. This can be done two different ways. You can add the `useHttp` option when configuring the module, which will be passed on in the result of `authenticationSpecification()` calls.
let auth = require('@koopjs/auth-direct-file')('pass-in-your-secret', `${__dirname}/user-store.json`, { useHttp: true })
koop.register(auth)
## Notes on use with ArcGIS Online and ArcGIS Portal
This authorization plugin has been tested with ArcGIS Online and ArcGIS Enterprise. Note that these ArcGIS products appear to block or be impaired by SSH-tunneling tools like `ngrok`, so if you are trying to test a local Koop instance against Online or Enterprise, it may not work as otherwise expected. Generally, you'll have to do a "real" deployment to actually test authorization against these products.
Alternatively, you can set an environment variable `KOOP_AUTH_HTTP=true`. Either of these approaches inform [koop-output-geoservices](https://github.com/koopjs/koop-output-geoservices) to use `http` as the protocol of the `tokenServicesUrl`.
For enterprise versions of Portal earlier than 10.6, you may need to [import the root of your certificate into Portal's trust store](http://enterprise.arcgis.com/en/portal/10.5/administer/linux/import-a-certificate-into-the-portal.htm). We have observed the inability to store credentials for a secured Koop service on Portal instances that have not yet imported the root SSL certificate (of the Koop instance) into the trust-store.
## Notes on use with ArcGIS Online and ArcGIS Portal
This authorization plugin has been tested with ArcGIS Online and ArcGIS Portal. For versions of Portal earlier than 10.6, you may need to [import the root of your certificate into Portal's trust store](http://enterprise.arcgis.com/en/portal/10.5/administer/linux/import-a-certificate-into-the-portal.htm). We have observed the inability to store credentials for a secured Koop service on Portal instances that have not yet imported the root SSL certificate (of the Koop instance) into the trust-store.
[npm-image]: https://img.shields.io/npm/v/@koopjs/auth-direct-file.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/@koopjs/auth-direct-file
[travis-image]: https://travis-ci.org/koopjs/koop-auth-direct-file.svg?style=flat-square
[travis-url]: https://travis-ci.org/koopjs/koop-auth-direct-file
[greenkeeper-image]: https://badges.greenkeeper.io/koopjs/koop-auth-direct-file.svg
[greenkeeper-url]: https://greenkeeper.io/
## How to setup an app: Step by step guide
On this guide we will show you how to setup a new app with a secured provider. We will be using [Koop-CLI](https://github.com/koopjs/koop-cli).
## General notes on the authentication pattern used here
```
# Install Koop-CLI if needed
npm install -g @koopjs/cli
The authentication module implemented here uses a *direct authentication* pattern; it receives user credentials (username/password) from a client and authenticates those credentials against an identity/user-store. Requests with valid credentials are issued an access-token (a string of encoded-data); The access token is encoded with the use of a secret known only to the Koop server. The access-token expires and becomes invalid after a certain period (default of 60 minutes).
# Create a new Koop app
koop new app demo-app
cd demo-app
![get access token](https://gist.githubusercontent.com/rgwozdz/e44f3686abe40360532fbcc6dccf225d/raw/9768df32fc62e99ce7383c124cab8efdf45b1e18/koop-direct-auth-access-token.png)
# Add this Auth plugin
koop add provider @koopjs/auth-direct-file
In addition to directly accepting username and password, the `authenticate` method will also accept a valid token. If receivied, a new token (with new expiry time) is issued and returned.
# Create a file with all valid credentials
echo \[\\n\\t{ \"username\": \"admin\", \"password\": \"admin\" }\\n\] > src/user-store.json
The issued access-token should be attached to all subsequent service requests by the client. When the server receives a request, it will check for the presence of an access-token and reject any requests that are missing such token. If the token is present, the server attempts to decode it with its stored secret. Failure to decode results in a request rejection. Once decoded, the server checks the token's expiration-date and rejects any token with a date that is out of range. If the token is not expired, the request for the desired resource proceeds.
# Open src/plugins.js and replace:
# This line: const authDirectFile = require('@koopjs/auth-direct-file')
# For this line: const authDirectFile = require('@koopjs/auth-direct-file')('123456', `${__dirname}/user-store.json`, { useHttp: true });
![enter image description here](https://gist.githubusercontent.com/rgwozdz/e44f3686abe40360532fbcc6dccf225d/raw/9768df32fc62e99ce7383c124cab8efdf45b1e18/koop-direct-auth-resources.png)
# Install any provider
koop add provider koop-provider-carto
# Run the koop server
koop serve
# Try to access server (it will fail <- require an access token)
http://localhost:8080/koop-provider-carto/rest/services/common-data/twitter_t3chfest_reduced/FeatureServer/0
# Generate token using any of the credentials you placed at src/user-store.json
http://localhost:8080/koop-provider-carto/tokens?username=rich&password=rich
# Now retry to access service but adding the generated token
http://localhost:8080/koop-provider-carto/rest/services/common-data/twitter_t3chfest_reduced/FeatureServer/0?token=GENERATED_TOKEN
# That's it! you are done!
```

@@ -5,3 +5,2 @@ const fs = require('fs');

const { validateCredentials } = require('./validate-credentials');
const errorPrefix = 'Auth plugin: ';
const TOKEN_EXPIRATION_MINUTES = 60;

@@ -15,3 +14,3 @@

.default(TOKEN_EXPIRATION_MINUTES),
});
}).unknown();

@@ -33,3 +32,3 @@ let _tokenExpirationMinutes;

if (!result) {
throw new Error(`${errorPrefix}${userStoreFilePath} not found`);
throw new Error(`${userStoreFilePath} not found`);
}

@@ -45,3 +44,3 @@ _secret = secret;

if (error) {
throw new Error(`${errorPrefix}${error.details[0].message}`);
throw new Error(error.details[0].message);
}

@@ -55,2 +54,4 @@

authorize,
name: 'file-based-auth-store',
version: require('../package.json').version
};

@@ -105,3 +106,6 @@ }

async function authorize(req) {
let token = req.query?.token || req.headers['authorization'];
const { query = {}, body = {} } = req;
const headerToken = req.headers['authorization'] ?? req.headers['authorization'].replace(/^Bearer /, '');
const params = { ...query, ...body };
const token = headerToken || params.token;

@@ -108,0 +112,0 @@ if (!token) {

@@ -30,3 +30,3 @@ const helpers = require('./validate-credentials');

expect(error.message).toMatch(
/^Auth plugin: .+userz-store.json not found$/,
/userz-store.json not found$/,
);

@@ -33,0 +33,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc