api: Add Client.maxScope and Client.refreshTokenExpirySeconds options
This commit is contained in:
parent
768f0f541b
commit
39e1d2a9f4
|
@ -6,9 +6,25 @@ const schema = new mongoose.Schema(
|
|||
validRedirectUris: [{ type: String }],
|
||||
|
||||
// this implementation deals with public clients only, so the following fields are not required:
|
||||
// scope: {type: String, required: true, default: '*'}, // max possible scope
|
||||
// confidential: {type: Boolean}, // whether this is a non-public, aka confidential client
|
||||
// clientSecret: { type: String },
|
||||
|
||||
// Set `refreshTokenExpirySeconds` to null to issue no refresh tokens. Set
|
||||
// to a number of seconds to issue refresh tokens with that duration. No
|
||||
// infinite tokens are ever issued, set to big number to simulate that.
|
||||
refreshTokenExpirySeconds: {
|
||||
type: Number,
|
||||
required: false,
|
||||
defaultValue: null,
|
||||
min: 1, // 0 would make no sense, use `null` to issue no token
|
||||
max: 1000 * 24 * 60 * 60, // 1000 days, nearly 3 years
|
||||
},
|
||||
|
||||
// Set to a scope which cannot be exceeded when requesting client tokens.
|
||||
// Clients must manually request a scope that is smaller or equal to this
|
||||
// scope to get a valid response. Scopes are not automatically truncated.
|
||||
// Leave empty or set to `"*"` for unlimited scopes in this client.
|
||||
maxScope: { type: String, required: false },
|
||||
},
|
||||
{ timestamps: true },
|
||||
);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const router = require('express').Router();
|
||||
const passport = require('passport');
|
||||
const { URL } = require('url');
|
||||
const querystring = require('querystring');
|
||||
|
||||
const { AuthorizationCode, AccessToken, RefreshToken, Client } = require('../models');
|
||||
const wrapRoute = require('../_helpers/wrapRoute');
|
||||
|
@ -96,7 +95,7 @@ const isValidRedirectUriFor = (redirectUri) => (redirectUriPattern) => {
|
|||
// is because we cannot know beforehand which IP the OBS will be running at.
|
||||
// But since it is usually accessed via local IP, we can allow all local IP
|
||||
// ranges. This special case must only be used in clients that have a very
|
||||
// restricted maxScope as well, to prevent misuse should an attack through
|
||||
// restricted `maxScope` as well, to prevent misuse should an attack through
|
||||
// this be successful.
|
||||
// This special case does however enforce TLS ("https://"), for it prevents
|
||||
// usage in a non-TLS-secured web server. At least passive sniffing of the
|
||||
|
@ -173,6 +172,13 @@ router.get(
|
|||
});
|
||||
}
|
||||
|
||||
if (client.maxScope && !scopeIncludes(scope, client.maxScope)) {
|
||||
return redirectWithParams(res, redirectUri, {
|
||||
error: 'access_denied',
|
||||
error_description: 'the requested scope is not valid for this client',
|
||||
});
|
||||
}
|
||||
|
||||
// Ok, let's save all this in the session, and show a dialog for the
|
||||
// decision to the user.
|
||||
|
||||
|
@ -303,21 +309,25 @@ router.get(
|
|||
await AuthorizationCode.deleteOne({ _id: authorizationCode._id });
|
||||
|
||||
const accessToken = AccessToken.generate(authorizationCode.client, authorizationCode.user, authorizationCode.scope);
|
||||
await accessToken.save();
|
||||
|
||||
const refreshToken = RefreshToken.generate(
|
||||
authorizationCode.client,
|
||||
authorizationCode.user,
|
||||
authorizationCode.scope,
|
||||
);
|
||||
|
||||
await Promise.all([accessToken.save(), refreshToken.save()]);
|
||||
let refreshToken;
|
||||
if (client.refreshTokenExpirySeconds != null) {
|
||||
refreshToken = RefreshToken.generate(
|
||||
authorizationCode.client,
|
||||
authorizationCode.user,
|
||||
authorizationCode.scope,
|
||||
client.refreshTokenExpirySeconds,
|
||||
);
|
||||
await refreshToken.save();
|
||||
}
|
||||
|
||||
return res.json({
|
||||
access_token: accessToken.token,
|
||||
token_type: 'Bearer',
|
||||
expires_in: Math.round((accessToken.expiresAt - new Date().getTime()) / 1000),
|
||||
refresh_token: refreshToken.token,
|
||||
scope: accessToken.scope,
|
||||
...(refreshToken != null ? { refresh_token: refreshToken.token } : {}),
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue