lib-oauth-tooling
A simple typescript based library for supporting OAuth2 flows.
Currently the following flows are supported:
See STUPS documentation and OAuth2 documentation for more information.
Migrating to 2.x.x
If you depend on the realm
property you now have to pass the value via the queryParams
parameters in OAuthConfig
:
getAccessToken({
realm: EMPLOYEES_REALM,
})
.then(token => {
});
getAccessToken({
queryParams: { realm: '/employees' }
})
.then(token => {
});
See the changelog for more information.
Usage
Note: node >= 6.0.0
required to consume this library.
Run npm install lib-oauth-tooling
.
Import a member of this lib like so (of course ES5 syntax is working as well...):
import {
TokenCache,
handleOAuthRequestMiddleware,
requireScopesMiddleware,
...
} from 'lib-oauth-tooling';
TokenCache(tokenConfig: { [key: string]: string[] }, oauthConfig: OAuthConfig)
Class to request and cache tokens on client-side.
const tokenCache = new TokenCache({
'service-foo': ['foo.read', 'foo.write'],
'service-bar': ['bar.read']
}, oAuthConfig);
tokenCache.get('service-foo')
.then((tokeninfo) => {
console.log(tokeninfo.access_token);
});
oauthConfig
:
credentialsDir
stringgrantType
string (AUTHORIZATION_CODE_GRANT
| PASSWORD_CREDENTIALS_GRANT
)accessTokenEndpoint
stringtokenInfoEndpoint
string - mandatory for TokenCachescopes
string optionalqueryParams
{} optionalredirect_uri
string optional (required with AUTHORIZATION_CODE_GRANT
)code
string optional (required with AUTHORIZATION_CODE_GRANT
)
handleOAuthRequestMiddleware(options: MiddlewareOptions)
Express middleware to extract and validate an access token. It attaches the scopes matched by the token to the request (request.scopes
) for further usage.
If the token is not valid the request is rejected (with 401 Unauthorized).
app.use(handleOAuthRequestMiddleware({
publicEndpoints: ['/heartbeat', '/status'],
tokenInfoEndpoint: 'auth.example.com/tokeninfo'
});
options
:
publicEndpoints
string[]tokenInfoEndpoint
string
requireScopesMiddleware(scopes: string[])
Specifies the scopes needed to access an endpoint. Assumes that there is an request.scopes
property (as attached by handleOAuthRequestMiddleware
) to match the required scopes against.
If the the requested scopes are not matched request is rejected (with 403 Forbidden).
app.get('/secured/route', requireScopesMiddleware(['scopeA', 'scopeB']), (request, response) => {
})
getTokenInfo(tokenInfoEndpoint: string, accessToken: string): Promise
Makes a request to the tokenInfoEndpoint
to validate the given accessToken
.
getTokenInfo(tokenInfoEndpoint, accessToken)
.then((tokeninfo) => {
console.log(tokeninfo.access_token);
})
.catch((err) => {
console.log(err);
});
getAccessToken(options: OAuthConfig)
Helper function to get an access token for the specified scopes.
getAccessToken(options)
.then((accessToken) => {
console.log(accessToken);
})
.catch((err) => {
console.log(err);
});
options
:
credentialsDir
stringgrantType
string (AUTHORIZATION_CODE_GRANT
| PASSWORD_CREDENTIALS_GRANT
| REFRESH_TOKEN_GRANT
)accessTokenEndpoint
stringscopes
string optionalqueryParams
{} optionalredirect_uri
string optional (required with AUTHORIZATION_CODE_GRANT
)code
string optional (required with AUTHORIZATION_CODE_GRANT
)refreshToken
string optional (required with REFRESH_TOKEN_GRANT)
AUTHORIZATION_CODE_GRANT
String constant specifying the Authorization Code Grant type.
PASSWORD_CREDENTIALS_GRANT
String constant specifying the Resource Owner Password Credentials Grant type.
REFRESH_TOKEN_GRANT
String constant specifying the Refresh Token Grant type.
Mock tooling
If you want to test oAuth locally without being able to actually call real endpoints this library provides some tooling.
mockTokenInfoEndpoint(options: MockOptions)
Mocks a tokeninfo
endpoint.
mockTokeninfoEndpoint({
url: 'http://some.oauth.endpoint/tokeninfo',
tokens: [{
access_token: 'someToken123',
scope: ['uid', 'something.read', 'something.write']
}],
times: 1
});
options
:
url
string (url of the tokeninfo
endpoint)tokens
any optional (list of valid tokens)times
number optional (for how many times/calls the endpoint is mocked, default is Number.MAX_SAFE_INTEGER
)
mockAccessTokenEndpoint(options: MockOptions)
Mocks a access_token
endpoint.
mockAccessTokenEndpoint({
url: 'http://some.oauth.endpoint/access_token',
times: 1
});
options
:
url
string (url of the access_token
endpoint)times
number optional (for how many times/calls the endpoint is mocked, default is Number.MAX_SAFE_INTEGER
)
cleanMock()
Cleans all nock
mocks (not only from this lib, really ALL) and given tokens.
Helpful when having multiple tests in a test suite, you can call cleanMock()
in the afterEach()
callback for example.
cleanMock();
Development
- clone this repo
npm install
- to build:
tsc
- to lint:
npm run tslint
Testing
npm test
- runs all testsnpm run unit-test
- runs unit testsnpm run integration-test
- runs integration tests
Changelog
2.0.0
- BREAKING
The (zalando-specific) realm
property was removed from OAuthConfig
. Also, the corresponding constants (SERVICES_REALM
and EMPLYEES_REALM
) were removed. Instead, you can add the realm (and arbitrary other query parameters) via the queryParams
property in OAuthConfig
.
1.0.0
- BREAKING
The signature of requireScopesMiddleware
is now incompatible with previous versions, precedenceFunction?
is now part of precedenceOptions?
.
License
MIT
authmosphere 2.0.0
- BREAKING
General changes
The following functions got support for an optional logger:
Providing a logger is optional. Any logger needs to satisfy the Logger interface.
To keep arguments lists short, option
objects were introduced to group a number of (mostly) optional parameters.
Express middlewares
Changed TokenCache
parameter type
The TokenCacheConfig
parameter type is now called TokenCacheOptions
and looks like:
type CacheConfig = {
percentageLeft: number
};
type TokenCacheOptions = {
cacheConfig?: CacheConfig,
logger?: Logger
};
Improved OAuthConfig
type
Restructuring
Instead of providing one bulky type for all OAuth2 grants the type OAuthConfig
is split up into a union type of all supported grants. A type for the TokenCache
config (TokenCacheOAuthConfig
) is also derived:
type OAuthConfig =
ClientCredentialsGrantConfig |
AuthorizationCodeGrantConfig |
PasswordCredentialsGrantConfig |
RefreshGrantConfig;
type TokenCacheOAuthConfig = OAuthConfig & {
tokenInfoEndpoint: string;
};
Passing optional body parameters
It is now possible to provide an optional object bodyParams
which will be appended to the request body when requesting a token (via getAccessToken
or TokenCache
):
const config: OAuthConfig = {
...,
bodyParams: {
business_partner_id: 'xxx-xxx-xxx'
}
};
Passing credentials
It is now possible to provide client (and user) credentials as a string
instead of just via a credentialsDir
:
const config: OAuthConfig = {
...,
clientId,
clientSecret,
applicationUsername,
applicationPassword
};
For detailed information have a look at the implementation of OAuthConfig
.
Improved OAuthGrantType
Instead of four single string values, an enum OAuthGrantType
is exported which should be used as grantType
in OAuthConfig
:
enum OAuthGrantType {
AUTHORIZATION_CODE_GRANT = 'authorization_code',
PASSWORD_CREDENTIALS_GRANT = 'password',
REFRESH_TOKEN_GRANT = 'refresh_token',
CLIENT_CREDENTIALS_GRANT = 'client_credentials'
}
More specific typing in createAuthCodeRequestUri
The type for the optional parameter queryParams
is changed from {}
to the more specific { [index: string]: string }
.
Mock tooling
mockAccessTokenEndpoint
respects scopes property
Before this release, mockAccessTokenEndpoint
always includes uid
as value of the scopes
property in the returned token. Now, mockAccessTokenEndpoint
includes the scopes which were requested by the HTTP request. A request like:
getAccessToken({
...,
scopes: ['uid', 'test']
})
...will lead to a response with a token which includes the scopes uid
and test
. If no scopes
are requested, the scopes
property of the token will be undefined
.
mockTokeninfoEndpoint
parameters
Token was moved out of MockOptions
into a separate parameter: mockTokeninfoEndpoint(options: MockOptions, tokens?: Token[]): nock.Scope
.
New functionality to test OAuth behavior in case of error
mockWithErrorResponse
The library now exports mockTokeninfoEndpointWithErrorResponse
and mockAccessTokenEndpointWithErrorResponse
which allow to mock an OAuth endpoint with an error response to be able to test behaviour in error case more accurate:
mockTokeninfoEndpointWithErrorResponse(options: MockOptions, httpStatus: number, responseBody?: object): void
mockAccessTokenEndpointWithErrorResponse(options: MockOptions, httpStatus: number, responseBody?: object): void
Both functions set up a HTTP mock via nock. A request to the mocked url (defined via MockOptions
) will lead to a response with the given httpStatus
and, if defined, responseBody
(otherwise {}
).
Improved error handling
Promises returned by getAccessToken
and getTokenInfo
are now rejected in a consistent way with an error object like:
{
error?: string | Error | object,
message?: string
}