Model Specification
Version >=5.x: Callback support has been removed! Each model function supports either sync or async (Promise orasyncfunction) return values.
Version <=4.x: Each model function supportspromises,Node-style callbacks,ES6 generators andasync/await (usingBabel). Note that promise support implies support for returning plain values where asynchronism is not required.
constmodel={// We support returning promises.getAccessToken:function(){returnnewPromise('works!');},// Or sync-style valuesgetAuthorizationCode:function(){return'works!'},// Or, using generators.getClient:function*(){yieldsomethingAsync();return'works!';},// Or, async/wait (using Babel).getUser:asyncfunction(){awaitsomethingAsync();return'works!';}};constOAuth2Server=require('@node-oauth/oauth2-server');letoauth=newOAuth2Server({model:model});
Code examples on this page usepromises.
generateAccessToken(client,user,scope)
Invoked to generate a new access token.
This model function isoptional. If not implemented, a default handler is used that generates access tokens consisting of 40 characters in the range ofa..z0..9.
Invoked during:
authorization_codegrantclient_credentialsgrantrefresh_tokengrantpasswordgrant
Arguments:
Name | Type | Description |
|---|---|---|
client | Object | The client the access token is generated for. |
user | Object | The user the access token is generated for. |
scope | String[] | The scopes associated with the access token. Can be |
Return value:
AString to be used as access token.
RFC 6749 Appendix A.12 specifies that access tokens must consist of characters inside the range0x20..0x7E (i.e. only printable US-ASCII characters).
Remarks:
client is the object previously obtained throughModel#getClient().
user is the user object previously obtained throughModel#getAuthorizationCode() (code.user; authorization code grant),Model#getUserFromClient() (client credentials grant),Model#getRefreshToken() (token.user; refresh token grant) orModel#getUser() (password grant).
generateRefreshToken(client,user,scope)
Invoked to generate a new refresh token.
This model function isoptional. If not implemented, a default handler is used that generates refresh tokens consisting of 40 characters in the range ofa..z0..9.
Invoked during:
authorization_codegrantrefresh_tokengrantpasswordgrant
Arguments:
Name | Type | Description |
|---|---|---|
client | Object | The client the refresh token is generated for. |
user | Object | The user the refresh token is generated for. |
scope | String[] | The scopes associated with the refresh token. Can be |
Return value:
AString to be used as refresh token.
RFC 6749 Appendix A.17 specifies that refresh tokens must consist of characters inside the range0x20..0x7E (i.e. only printable US-ASCII characters).
Remarks:
client is the object previously obtained throughModel#getClient().
user is the user object previously obtained throughModel#getAuthorizationCode() (code.user; authorization code grant),Model#getRefreshToken() (token.user; refresh token grant) orModel#getUser() (password grant).
generateAuthorizationCode(client,user,scope)
Invoked to generate a new authorization code.
This model function isoptional. If not implemented, a default handler is used that generates authorization codes consisting of 40 characters in the range ofa..z0..9.
Invoked during:
authorization_codegrant
Arguments:
Name | Type | Description |
|---|---|---|
client | Object | The client the authorization code is generated for. |
user | Object | The user the authorization code is generated for. |
scope | String[] | The scopes associated with the authorization code. Can be |
Return value:
AString to be used as authorization code.
RFC 6749 Appendix A.11 specifies that authorization codes must consist of characters inside the range0x20..0x7E (i.e. only printable US-ASCII characters).
getAccessToken(accessToken)
Invoked to retrieve an existing access token previously saved throughModel#saveToken().
This model function isrequired ifOAuth2Server#authenticate() is used.
Invoked during:
request authentication
Arguments:
Name | Type | Description |
|---|---|---|
accessToken | String | The access token to retrieve. |
Return value:
AnObject representing the access token and associated data.
Name | Type | Description |
|---|---|---|
token | Object | The return value. |
token.accessToken | String | The access token passed to |
token.accessTokenExpiresAt | Date | The expiry time of the access token. |
[token.scope] | String[] | The authorized scope of the access token. |
token.client | Object | The client associated with the access token. |
token.client.id | String | A unique string identifying the client. |
token.user | Object | The user associated with the access token. |
token.client andtoken.user can carry additional properties that will be ignored byoauth2-server.
Remarks:
functiongetAccessToken(accessToken){// imaginary DB queriesreturndb.queryAccessToken({access_token:accessToken}).then(function(token){returnPromise.all([token,db.queryClient({id:token.client_id}),db.queryUser({id:token.user_id})]);}).spread(function(token,client,user){return{accessToken:token.access_token,accessTokenExpiresAt:token.expires_at,scope:token.scope,client:client,// with 'id' propertyuser:user};});}
getRefreshToken(refreshToken)
Invoked to retrieve an existing refresh token previously saved throughModel#saveToken().
This model function isrequired if therefresh_token grant is used.
Invoked during:
refresh_tokengrant
Arguments:
Name | Type | Description |
|---|---|---|
refreshToken | String | The access token to retrieve. |
Return value:
AnObject representing the refresh token and associated data.
token.client andtoken.user can carry additional properties that will be ignored byoauth2-server.
Remarks:
functiongetRefreshToken(refreshToken){// imaginary DB queriesreturndb.queryRefreshToken({refresh_token:refreshToken}).then(function(token){returnPromise.all([token,db.queryClient({id:token.client_id}),db.queryUser({id:token.user_id})]);}).spread(function(token,client,user){return{refreshToken:token.refresh_token,refreshTokenExpiresAt:token.expires_at,scope:token.scope,client:client,// with 'id' propertyuser:user};});}
getAuthorizationCode(authorizationCode)
Invoked to retrieve an existing authorization code previously saved throughModel#saveAuthorizationCode().
This model function isrequired if theauthorization_code grant is used.
Invoked during:
authorization_codegrant
Arguments:
Name | Type | Description |
|---|---|---|
authorizationCode | String | The authorization code to retrieve. |
Return value:
AnObject representing the authorization code and associated data.
code.client andcode.user can carry additional properties that will be ignored byoauth2-server.
Remarks:
functiongetAuthorizationCode(authorizationCode){// imaginary DB queriesreturndb.queryAuthorizationCode({authorization_code:authorizationCode}).then(function(code){returnPromise.all([code,db.queryClient({id:code.client_id}),db.queryUser({id:code.user_id})]);}).spread(function(code,client,user){return{authorizationCode:code.authorization_code,expiresAt:code.expires_at,redirectUri:code.redirect_uri,scope:code.scope,client:client,// with 'id' propertyuser:user};});}
getClient(clientId,clientSecret)
Invoked to retrieve a client using a client id or a client id/client secret combination, depending on the grant type.
This model function isrequired for all grant types.
Invoked during:
authorization_codegrantclient_credentialsgrantrefresh_tokengrantpasswordgrant
Arguments:
Name | Type | Description |
|---|---|---|
clientId | String | The client id of the client to retrieve. |
clientSecret | String | The client secret of the client to retrieve. Can be |
Return value:
AnObject representing the client and associated data, or a falsy value if no such client could be found.
Name | Type | Description |
|---|---|---|
client | Object | The return value. |
client.id | String | A unique string identifying the client. |
[client.redirectUris] | Array<String> | Redirect URIs allowed for the client. Required for the |
client.grants | Array<String> | Grant types allowed for the client. |
[client.accessTokenLifetime] | Number | Client-specific lifetime of generated access tokens in seconds. |
[client.refreshTokenLifetime] | Number | Client-specific lifetime of generated refresh tokens in seconds. |
The return value (client) can carry additional properties that will be ignored byoauth2-server.
Remarks:
functiongetClient(clientId,clientSecret){// imaginary DB queryletparams={client_id:clientId};if(clientSecret){params.client_secret=clientSecret;}returndb.queryClient(params).then(function(client){return{id:client.id,redirectUris:client.redirect_uris,grants:client.grants};});}
getUser(username,password,client)
Invoked to retrieve a user using a username/password combination.
This model function isrequired if thepassword grant is used.
Invoked during:
passwordgrant
Arguments:
Return value:
AnObject representing the user, or a falsy value if no such user could be found. The user object is completely transparent tooauth2-server and is simply used as input to other model functions.
Remarks:
functiongetUser(username,password){// imaginary DB queryreturndb.queryUser({username:username,password:password});}
getUserFromClient(client)
Invoked to retrieve the user associated with the specified client.
This model function isrequired if theclient_credentials grant is used.
Invoked during:
client_credentialsgrant
Arguments:
Name | Type | Description |
|---|---|---|
client | Object | The client to retrieve the associated user for. |
client.id | String | A unique string identifying the client. |
Return value:
AnObject representing the user, or a falsy value if the client does not have an associated user. The user object is completely transparent tooauth2-server and is simply used as input to other model functions.
Remarks:
client is the object previously obtained throughModel#getClient().
functiongetUserFromClient(client){// imaginary DB queryreturndb.queryUser({id:client.user_id});}
saveToken(token,client,user)
Invoked to save an access token and optionally a refresh token, depending on the grant type.
This model function isrequired for all grant types.
Invoked during:
authorization_codegrantclient_credentialsgrantrefresh_tokengrantpasswordgrant
Arguments:
Return value:
AnObject representing the token(s) and associated data.
Name | Type | Description |
|---|---|---|
token | Object | The return value. |
token.accessToken | String | The access token passed to |
token.accessTokenExpiresAt | Date | The expiry time of the access token. |
token.refreshToken | String | The refresh token passed to |
token.refreshTokenExpiresAt | Date | The expiry time of the refresh token. |
[token.scope] | String[] | The authorized scope of the access token. |
token.client | Object | The client associated with the access token. |
token.client.id | String | A unique string identifying the client. |
token.user | Object | The user associated with the access token. |
token.client andtoken.user can carry additional properties that will be ignored byoauth2-server.
If theallowExtendedTokenAttributes server option is enabled (seeOAuth2Server#token()) any additional attributes set on the result are copied to the token response sent to the client.
Remarks:
functionsaveToken(token,client,user){// imaginary DB queriesletfns=[db.saveAccessToken({access_token:token.accessToken,expires_at:token.accessTokenExpiresAt,scope:token.scope,client_id:client.id,user_id:user.id}),db.saveRefreshToken({refresh_token:token.refreshToken,expires_at:token.refreshTokenExpiresAt,scope:token.scope,client_id:client.id,user_id:user.id})];returnPromise.all(fns);.spread(function(accessToken,refreshToken){return{accessToken:accessToken.access_token,accessTokenExpiresAt:accessToken.expires_at,refreshToken:refreshToken.refresh_token,refreshTokenExpiresAt:refreshToken.expires_at,scope:accessToken.scope,client:{id:accessToken.client_id},user:{id:accessToken.user_id}};});}
saveAuthorizationCode(code,client,user)
Invoked to save an authorization code.
This model function isrequired if theauthorization_code grant is used.
Invoked during:
authorization_codegrant
Arguments:
Name | Type | Description |
|---|---|---|
code | Object | The code to be saved. |
code.authorizationCode | String | The authorization code to be saved. |
code.expiresAt | Date | The expiry time of the authorization code. |
code.redirectUri | String | The redirect URI associated with the authorization code. |
[code.scope] | String[] | The authorized scope of the authorization code. |
client | Object | The client associated with the authorization code. |
user | Object | The user associated with the authorization code. |
Todo
Iscode.scope really optional?
Return value:
AnObject representing the authorization code and associated data.
code.client andcode.user can carry additional properties that will be ignored byoauth2-server.
Remarks:
functionsaveAuthorizationCode(code,client,user){// imaginary DB queriesletauthCode={authorization_code:code.authorizationCode,expires_at:code.expiresAt,redirect_uri:code.redirectUri,scope:code.scope,client_id:client.id,user_id:user.id};returndb.saveAuthorizationCode(authCode).then(function(authorizationCode){return{authorizationCode:authorizationCode.authorization_code,expiresAt:authorizationCode.expires_at,redirectUri:authorizationCode.redirect_uri,scope:authorizationCode.scope,client:{id:authorizationCode.client_id},user:{id:authorizationCode.user_id}};});}
revokeToken(token)
Invoked to revoke a refresh token.
This model function isrequired if therefresh_token grant is used.
Invoked during:
refresh_tokengrant
Arguments:
Name | Type | Description |
|---|---|---|
token | Object | The token to be revoked. |
token.refreshToken | String | The refresh token. |
[token.refreshTokenExpiresAt] | Date | The expiry time of the refresh token. |
[token.scope] | String[] | The authorized scope of the refresh token. |
token.client | Object | The client associated with the refresh token. |
token.client.id | String | A unique string identifying the client. |
token.user | Object | The user associated with the refresh token. |
Return value:
Returntrue if the revocation was successful orfalse if the refresh token could not be found.
Remarks:
token is the refresh token object previously obtained throughModel#getRefreshToken().
functionrevokeToken(token){// imaginary DB queriesreturndb.deleteRefreshToken({refresh_token:token.refreshToken}).then(function(refreshToken){return!!refreshToken;});}
revokeAuthorizationCode(code)
Invoked to revoke an authorization code.
This model function isrequired if theauthorization_code grant is used.
Invoked during:
authorization_codegrant
Arguments:
Name | Type | Description |
|---|---|---|
code | Object | The return value. |
code.code | String | The authorization code. |
code.expiresAt | Date | The expiry time of the authorization code. |
[code.redirectUri] | String | The redirect URI of the authorization code. |
[code.scope] | String[] | The authorized scope of the authorization code. |
code.client | Object | The client associated with the authorization code. |
code.client.id | String | A unique string identifying the client. |
code.user | Object | The user associated with the authorization code. |
Return value:
Returntrue if the revocation was successful orfalse if the authorization code could not be found.
Remarks:
code is the authorization code object previously obtained throughModel#getAuthorizationCode().
functionrevokeAuthorizationCode(code){// imaginary DB queriesreturndb.deleteAuthorizationCode({authorization_code:code.authorizationCode}).then(function(authorizationCode){return!!authorizationCode;});}
validateScope(user,client,scope)
Invoked to check if the requestedscope is valid for a particularclient/user combination.
This model function isoptional. If not implemented, any scope is accepted.
Invoked during:
authorization_codegrantclient_credentialsgrantpasswordgrant
Arguments:
Name | Type | Description |
|---|---|---|
user | Object | The associated user. |
client | Object | The associated client. |
client.id | Object | A unique string identifying the client. |
scope | String[] | The scopes to validate. |
Return value:
Validated scopes to be used or a falsy value to reject the requested scopes.
Remarks:
user is the user object previously obtained throughModel#getAuthorizationCode() (code.user; authorization code grant),Model#getUserFromClient() (client credentials grant) orModel#getUser() (password grant).
client is the object previously obtained throughModel#getClient (all grants).
You can decide yourself whether you want to reject or accept partially valid scopes by simply filtering out invalid scopes and returning only the valid ones.
To reject invalid or only partially valid scopes:
// list of valid scopesconstVALID_SCOPES=['read','write'];functionvalidateScope(user,client,scope){if(!scope.every(s=>VALID_SCOPES.indexOf(s)>=0)){returnfalse;}returnscope;}
To accept partially valid scopes:
// list of valid scopesconstVALID_SCOPES=['read','write'];functionvalidateScope(user,client,scope){returnscope.filter(s=>VALID_SCOPES.indexOf(s)>=0);}
verifyScope(accessToken,scope)
Invoked during request authentication to check if the provided access token was authorized the requested scopes.
This model function isrequired if scopes are used withOAuth2Server#authenticate()but it’s never called, if you provide your ownauthenticateHandler to the options.
Invoked during:
request authentication
Arguments:
Name | Type | Description |
|---|---|---|
token | Object | The access token to test against |
token.accessToken | String | The access token. |
[token.accessTokenExpiresAt] | Date | The expiry time of the access token. |
[token.scope] | String[] | The authorized scope of the access token. |
token.client | Object | The client associated with the access token. |
token.client.id | String | A unique string identifying the client. |
token.user | Object | The user associated with the access token. |
scope | String[] | The required scopes. |
Return value:
Returnstrue if the access token passes,false otherwise.
Remarks:
token is the access token object previously obtained throughModel#getAccessToken().
scope is the required scope as given toOAuth2Server#authenticate() asoptions.scope.
functionverifyScope(token,requestedScopes){if(!token.scope){returnfalse;}letauthorizedScopes=token.scope;returnrequestedScopes.every(s=>token.scope.includes(scope));}
validateRedirectUri(redirectUri,client)
Invoked to check if the providedredirectUri is valid for a particularclient.
This model function isoptional. If not implemented, theredirectUri should be included in the providedredirectUris of the client.
Invoked during:
authorization_codegrant
Arguments:
Name | Type | Description |
|---|---|---|
redirect_uri | String | The redirect URI to validate. |
client | Object | The associated client. |
Return value:
Returnstrue if theredirectUri is valid,false otherwise.
Remarks:When implementing this method you should take care of possible security risks related toredirectUri... _rfc6819:https://datatracker.ietf.org/doc/html/rfc6819
Section-5.2.3.5 is implemented by default... _Section-5.2.3.5:https://datatracker.ietf.org/doc/html/rfc6819#section-5.2.3.5
functionvalidateRedirectUri(redirectUri,client){returnclient.redirectUris.includes(redirectUri);}