Authentication Plugin
Building your own authentication plugin
Learn how to create an authentication plugin to verify a users ability to connect, as well as provide data that can be used for permissioning further on.
You can see the code for this here
Configuring the plugin
- Via config.yml:
auth: - path: ./auth/token-authentication
- Via deepstream constructor:
import { Deepstream } from '@deepstream/server' export const deepstream = new Deepstream({ auth: [{ path: './auth/token-authentication', options: {} }] }) deepstream.start()
- Via deepstream setter:
import TokenAuthentication from './token-authentication' import { Deepstream } from '@deepstream/server' const deepstream = new Deepstream({}) deepstream.set('auth', new TokenAuthentication({}, deepstream.getServices())) deepstream.start()
Example Documented Plugin
import { DeepstreamPlugin, DeepstreamServices, DeepstreamAuthentication, DeepstreamAuthenticationResult } from '@deepstream/types'
import { Dictionary } from 'ts-essentials';
const TOKENS: Dictionary<DeepstreamAuthenticationResult> = {
'ABC': {
isValid: true,
id: 'John',
serverData: { admin: true },
clientData: { theme: 'red' }
},
'123': {
isValid: true,
id: 'Bob',
serverData: { admin: false },
clientData: { theme: 'blue' }
}
}
interface TokenAuthenticationOptions {
}
export default class TokenAuthentication extends DeepstreamPlugin implements DeepstreamAuthentication {
public description = 'Token Authentication'
private logger = this.services.logger.getNameSpace('HEADER_AUTHENTICATION')
constructor (private pluginOptions: TokenAuthenticationOptions, private services: Readonly<DeepstreamServices>) {
super()
}
/**
* The only API callback required for authentication.
*
* The callback signature is as follows:
*
* If user is found:
*
* return {
* isValid: boolean,
* id: uuid,
* clientData: {}, // data to send to client on login or login error
* serverData: {} // data used to authenticate users
* }
*
* // If user is not found, return null
* return null
*
* The username is the name to be used by permissions as well as presence. It doesn't have to be unique, but
* if more than one user with the same name is logged in the system doesn't behave any differently! So if you want
* each user to be unique you may need to add a uuid to distinguish between them.
*
* serverData is data is can be accessed throughout deepstream (mostly via permissioning and custom plugins) incase
* you want more context about the actual client
*
* clientData is returned to the client after a succesful login. This could be a token to allow them to login again
* without entering sensitive information or their favourite color preferences. However, it's worth noting that it's
* always recommended to use records because they are dynamic! ClientData should usually be login related, like session
* expiry time or such.
*/
async isValidUser(connectionData: any, authData: any) {
if (typeof authData.token !== 'string') {
return null
}
if (TOKENS[authData.token]) {
return TOKENS[authData.token]
}
// If an invalid token is provided then return null incase another auth
// handler can save the day
return null
}
}