1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-11-13 03:35:52 +01:00
verdaccio/website/docs/plugin-auth.md

304 lines
11 KiB
Markdown
Raw Normal View History

---
id: plugin-auth
title: "Authentication Plugin"
---
## What's an Authentication Plugin? {#whats-an-authentication-plugin}
Is a sort plugin that allows to handle who access or publish to a specific package. By default the `htpasswd` is built-in, but can
easily be replaced by your own.
## Getting Started
The authentication plugins are defined in the `auth:` section, as follows:
```yaml
auth:
htpasswd:
file: ./htpasswd
```
also multiple plugins can be chained:
```yaml
auth:
htpasswd:
file: ./htpasswd
anotherAuth:
foo: bar
bar: foo
lastPlugin:
foo: bar
bar: foo
```
> If one of the plugin in the chain is able to resolve the request, the next ones will be ignored.
## How do the authentication plugin works? {#how-do-the-authentication-plugin-works}
2021-09-01 19:13:09 +02:00
Basically we have to return an object with a single method called `authenticate` that will receive 3 arguments (`user, password, callback`).
On each request, `authenticate` will be triggered and the plugin should return the credentials, if the `authenticate` fails, it will fallback to the `$anonymous` role by default.
### API {#api}
```typescript
interface IPluginAuth<T> extends IPlugin<T> {
authenticate(user: string, password: string, cb: AuthCallback): void;
adduser?(user: string, password: string, cb: AuthCallback): void;
changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void;
allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
apiJWTmiddleware?(helpers: any): Function;
}
```
> Only `adduser`, `allow_access`, `apiJWTmiddleware`, `allow_publish` and `allow_unpublish` are optional, verdaccio provide a fallback in all those cases.
#### `apiJWTmiddleware` method {#apijwtmiddleware-method}
Since `v4.0.0`
`apiJWTmiddleware` was introduced on [PR#1227](https://github.com/verdaccio/verdaccio/pull/1227) in order to have full control of the token handler, overriding this method will disable `login/adduser` support. We recommend don't implement this method unless is totally necessary. See a full example [here](https://github.com/verdaccio/verdaccio/pull/1227#issuecomment-463235068).
## What should I return in each of the methods? {#what-should-i-return-in-each-of-the-methods}
Verdaccio relies on `callback` functions at time of this writing. Each method should call the method and what you return is important, let's review how to do it.
### `authentication` callback {#authentication-callback}
Once the authentication has been executed there is 2 options to give a response to `verdaccio`.
##### If the authentication fails {#if-the-authentication-fails}
If the auth was unsuccessful, return `false` as the second argument.
```typescript
callback(null, false)
```
##### If the authentication success {#if-the-authentication-success}
The auth was successful.
`groups` is an array of strings where the user is part of.
```
callback(null, groups);
```
##### If the authentication produce an error {#if-the-authentication-produce-an-error}
The authentication service might fails, and you might want to reflect that in the user response, eg: service is unavailable.
```
import { getInternalError } from '@verdaccio/commons-api';
callback(getInternalError('something bad message), null);
```
2021-09-01 19:13:09 +02:00
> A failure on login is not the same as service error, if you want to notify user the credentials are wrong, just return `false` instead string of groups. The behaviour mostly depends of you.
### `adduser` callback {#adduser-callback}
##### If adduser success {#if-adduser-success}
If the service is able to create an user, return `true` as the second argument.
```typescript
callback(null, true)
```
##### If adduser fails {#if-adduser-fails}
Any other action different than success must return an error.
```typescript
import { getConflict } from '@verdaccio/commons-api';
const err = getConflict('maximum amount of users reached');
callback(err);
```
### `changePassword` callback {#changepassword-callback}
##### If the request is successful {#if-the-request-is-successful}
If the service is able to create an user, return `true` as the second argument.
```typescript
const user = serviceUpdatePassword(user, password, newPassword);
callback(null, user)
```
##### If the request fails {#if-the-request-fails}
Any other action different than success must return an error.
```typescript
import { getNotFound } from '@verdaccio/commons-api';
const err = getNotFound('user not found');
callback(err);
```
### `allow_access`, `allow_publish`, or `allow_unpublish` callback {#allow_access-allow_publish-or-allow_unpublish-callback}
These methods aims to allow or deny trigger some actions.
##### If the request success {#if-the-request-success}
If the service is able to create an user, return a `true` as the second argument.
```typescript
allow_access(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
const isAllowed: boolean = checkAction(user, pkg);
callback(null, isAllowed)
}
```
##### If the request fails {#if-the-request-fails-1}
Any other action different than success must return an error.
```typescript
import { getNotFound } from '@verdaccio/commons-api';
const err = getForbidden('not allowed to access package');
callback(err);
```
## Generate an authentication plugin {#generate-an-authentication-plugin}
For detailed info check our [plugin generator page](plugin-generator). Run the `yo` command in your terminal and follow the steps.
```
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? service-name
? Select Language typescript
? What kind of plugin you want to create? auth
? Please, describe your plugin awesome auth plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,auth,awesome,verdaccio-plugin
create verdaccio-plugin-authservice-name/package.json
create verdaccio-plugin-authservice-name/.gitignore
create verdaccio-plugin-authservice-name/.npmignore
create verdaccio-plugin-authservice-name/jest.config.js
create verdaccio-plugin-authservice-name/.babelrc
create verdaccio-plugin-authservice-name/.travis.yml
create verdaccio-plugin-authservice-name/README.md
create verdaccio-plugin-authservice-name/.eslintrc
create verdaccio-plugin-authservice-name/.eslintignore
create verdaccio-plugin-authservice-name/src/index.ts
create verdaccio-plugin-authservice-name/index.ts
create verdaccio-plugin-authservice-name/tsconfig.json
create verdaccio-plugin-authservice-name/types/index.ts
create verdaccio-plugin-authservice-name/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
```
After the install finish, access to your project scalfold.
```
➜ cd verdaccio-plugin-service-name
➜ cat package.json
{
"name": "verdaccio-plugin-service-name",
"version": "0.0.1",
"description": "awesome auth plugin",
...
```
## Full implementation ES5 example {#full-implementation-es5-example}
```javascript
function Auth(config, stuff) {
var self = Object.create(Auth.prototype);
self._users = {};
// config for this module
self._config = config;
// verdaccio logger
self._logger = stuff.logger;
// pass verdaccio logger to ldapauth
self._config.client_options.log = stuff.logger;
return self;
}
Auth.prototype.authenticate = function (user, password, callback) {
var LdapClient = new LdapAuth(self._config.client_options);
....
LdapClient.authenticate(user, password, function (err, ldapUser) {
...
var groups;
...
callback(null, groups);
});
};
module.exports = Auth;
```
And the configuration will looks like:
```yaml
auth:
htpasswd:
file: ./htpasswd
```
Where `htpasswd` is the sufix of the plugin name. eg: `verdaccio-htpasswd` and the rest of the body would be the plugin configuration params.
### List Community Authentication Plugins {#list-community-authentication-plugins}
* [verdaccio-bitbucket](https://github.com/idangozlan/verdaccio-bitbucket): Bitbucket authentication plugin for verdaccio.
* [verdaccio-bitbucket-server](https://github.com/oeph/verdaccio-bitbucket-server): Bitbucket Server authentication plugin for verdaccio.
* [verdaccio-ldap](https://www.npmjs.com/package/verdaccio-ldap): LDAP auth plugin for verdaccio.
* [verdaccio-active-directory](https://github.com/nowhammies/verdaccio-activedirectory): Active Directory authentication plugin for verdaccio
* [verdaccio-gitlab](https://github.com/bufferoverflow/verdaccio-gitlab): use GitLab Personal Access Token to authenticate
* [verdaccio-gitlab-ci](https://github.com/lab360-ch/verdaccio-gitlab-ci): Enable GitLab CI to authenticate against verdaccio.
* [verdaccio-htpasswd](https://github.com/verdaccio/verdaccio-htpasswd): Auth based on htpasswd file plugin (built-in) for verdaccio
* [verdaccio-github-oauth](https://github.com/aroundus-inc/verdaccio-github-oauth): Github oauth authentication plugin for verdaccio.
* [verdaccio-github-oauth-ui](https://github.com/n4bb12/verdaccio-github-oauth-ui): GitHub OAuth plugin for the verdaccio login button.
* [verdaccio-groupnames](https://github.com/deinstapel/verdaccio-groupnames): Plugin to handle dynamic group associations utilizing `$group` syntax. Works best with the ldap plugin.
* [verdaccio-sqlite](https://github.com/bchanudet/verdaccio-sqlite): SQLite Authentication plugin for Verdaccio
* [verdaccio-okta-auth](https://github.com/hogarthww-labs/verdaccio-okta-auth) Verdaccio Okta Auth
* [verdaccio-azure-ad-login](https://github.com/IhToN/verdaccio-azure-ad-login) Let your users authenticate into Verdaccio via Azure AD OAuth 2.0 API
* [verdaccio-auth-gitlab](https://github.com/pfdgithub/verdaccio-auth-gitlab) Verdaccio authentication plugin by gitlab personal access tokens.
**Have you developed a new plugin? Add it here !**