Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const express = require('express');
- const sha256 = require('sha256');
- const bodyParser = require('body-parser');
- const OAuth2Server = require('oauth2-server');
- const cors = require('cors');
- const app = express();
- app.use(cors());
- // kljucni vrstici
- app.use(bodyParser.urlencoded({ extended: true }));
- app.use(bodyParser.json());
- /***************Mongodb configuratrion********************/
- var mongoose = require('mongoose');
- var configDB = require('./config/database.js');
- //configuration ===============================================================
- mongoose.connect(
- configDB.url,
- { useNewUrlParser: true }
- ); // connect to our database
- require('./models/Post');
- require('./models/Comment');
- require('./models/User');
- require('./models/Client');
- require('./models/Token');
- const apiPost = require('./api/apiPosts');
- const router = express.Router();
- const User = mongoose.model('User');
- const Client = mongoose.model('Client');
- const Token = mongoose.model('Token');
- /*
- https://alexbilbie.com/guide-to-oauth-2-grants/
- https://tools.ietf.org/html/rfc6749.html
- https://oauth2-server.readthedocs.io/en/latest/model/overview.html
- https://oauth2-server.readthedocs.io/en/latest/model/spec.html
- password grant:
- getClient -> getUser -> validateScope -> generateAccessToken(optional) ->
- -> generateRefreshToken(optional) -> saveToken
- refresh_token grant:
- getClient -> getRefreshToken
- (ce naj vrne novi refresh token [alwaysIssueNewRefreshToken: true] potem se kličeju tudi)
- -> revokeToken -> generateAccessToken -> generateRefreshToken -> saveToken
- pri avtentikaciji:
- getAccessToken -> verifyScope
- */
- const ACCES_TOKEN_VALIDATION_HOURS = 1.0;
- // @ts-ignore
- const oauth = new OAuth2Server({
- model: {
- generateAccessToken(client, user, scope) {
- console.log('generateAccessToken');
- // če iz te funkcije ne vrnete nič, potem se ustvari default vrednost
- },
- generateRefreshToken(client, user, scope) {
- console.log('generateRefreshToken');
- // če iz te funkcije ne vrnete nič, potem se ustvari default vrednost
- },
- async getClient(clientId, clientSecret) {
- // poišči klienta v bazi in ga vrni
- console.log('getClient');
- const allClinets = await Client.find({});
- console.log(allClinets);
- const client = await Client.findOne({ name: 'MyApp' });
- return client;
- /*return {
- id: 'MyApp',
- // redirectUris: [''],
- grants: ['password', 'refresh_token'], // mora se nastaviti, za tiste grante ki jih dovolite
- }*/
- },
- getUserFromClient(client) {
- console.log('getUserFromClient');
- },
- async getUser(username, password) {
- // poišči uporabnika v bazi in ga vrni
- console.log('getUser');
- const user = await User.findOne({
- username: username,
- password: sha256(password)
- });
- console.log('USER: ', user);
- return user;
- /*return {
- username: 'goran.hrovat',
- role: 'admin'
- };*/
- },
- async saveToken(token, client, user) {
- // v bazo shrani access in refresh token in ga nato vrni v objketu (glej primer)
- console.log(
- 'saveToken ' +
- JSON.stringify(token) +
- ' user: ' +
- JSON.stringify(user) +
- ' client ' +
- JSON.stringify(client)
- );
- var token = new Token({
- accessToken: token.accessToken,
- accessTokenExpiresAt: token.accessTokenExpiresAt,
- refreshToken: token.refreshToken,
- refreshTokenExpiresAt: token.refreshTokenExpiresAt,
- scope: user.scope,
- role: user.role,
- client: client._id,
- user: user._id,
- username: user.username,
- fullname: user.name + ' ' + user.surname
- });
- await token.save();
- return token;
- /*return {
- accessToken: token.accessToken,
- accessTokenExpiresAt: token.accessTokenExpiresAt,
- refreshToken: token.refreshToken,
- refreshTokenExpiresAt: token.refreshTokenExpiresAt,
- scope: token.scope,
- client: {id: client.id},
- user: {id: user.username}
- }*/
- },
- validateScope(user, client, scope) {
- // uporabnik zahteva določen scope in tu spustimo naprej samo scope, ki jih dovolimo
- // ne rabimo mu odobriti vseh scopov, ki jih zahteva
- // dovoljeni scopi uporabnika so ponavadi zapisani v bazi
- // scope je poljuben niz, ponavadi več scopov ločimo z vejico
- console.log('validateScope ' + JSON.stringify(scope));
- const VALID_SCOPES = ['read', 'write'];
- return scope
- .split(' ')
- .filter(s => VALID_SCOPES.indexOf(s) >= 0)
- .join(' ');
- },
- generateAuthorizationCode(code, client, user) {
- console.log('generateAuthorizationCode');
- },
- async getAccessToken(accessToken) {
- console.log('getAccessToken: ' + accessToken);
- // če najdeš token v bazi (shranjen je bil v funkciji saveToken) vrni objekt s tokenom
- // drugace null ali false
- const token = await Token.findOne({ accessToken: accessToken });
- return token;
- /*
- var myDate = new Date();
- myDate.setTime(
- myDate.getTime() + ACCES_TOKEN_VALIDATION_HOURS * 60 * 60 * 1000
- );
- return {
- accessToken: accessToken,
- accessTokenExpiresAt: myDate,
- scope: 'read write',
- client: { id: 'MyApp' }, // with 'id' property
- user: { username: 'goran.hrovat', role: 'admin' }
- };*/
- },
- getAuthorizationCode(authorizationCode) {
- console.log('getAuthorizationCode');
- },
- async getRefreshToken(refreshToken) {
- console.log('getRefreshToken ' + JSON.stringify(refreshToken));
- // poišči refresh token v bazi, shranjen v funkciji saveToken
- const token = await Token.findOne({ refreshToken: refreshToken });
- return token;
- /*return {
- refreshToken: refreshToken,
- scope: 'read write',
- client: { id: 'MyApp' }, // with 'id' property
- user: { username: 'goran.hrovat', role: 'admin' }
- };*/
- },
- revokeAuthorizationCode(code) {
- console.log('revokeAuthorizationCode');
- },
- revokeToken(token) {
- // iz baze pobriši refresh token
- console.log('revokeToken: ' + JSON.stringify(token));
- // če najdes vrneš, true drugače false
- return true;
- },
- saveAuthorizationCode(code, client, user) {
- console.log('saveAuthorizationCode');
- },
- verifyScope(accessToken, scope) {
- // zahtevan scope je v scope, ki se poda pri klicu authenicate za api metodo
- // scope, ki je dovoljen userju je shranjen v accessToken.scope,
- // scope, ki ga uporabnik hoče uveljavit pa v argumentu scope
- console.log(
- 'verifyScope: ' + JSON.stringify(accessToken) + ' scope: ' + scope
- );
- if (!accessToken.scope) {
- return false;
- }
- let requestedScopes = scope.split(' ');
- let authorizedScopes = accessToken.scope.split(' ');
- return requestedScopes.every(s => authorizedScopes.indexOf(s) >= 0);
- }
- }
- // requireClientAuthentication: false,
- // grants: ['refresh_token', 'password'],
- // accessTokenLifetime: 60 * 60 * 24,
- // alwaysIssueNewRefreshToken: true, // default = true
- });
- // endpoint za pridobivanje access in refresh tokena
- app.post('/oauth/token', async function(req, res, next) {
- console.log('oauth/token');
- var request = new OAuth2Server.Request(req);
- var response = new OAuth2Server.Response(res);
- try {
- let token = await oauth.token(request, response);
- // Todo: remove unnecessary values in response
- // console.log("oauth.token: " + JSON.stringify(token));
- return res.json(token);
- } catch (err) {
- return res.status(err.code || 500).json(err);
- }
- });
- // middleware za authentikacijo, ki se uporabi pri REST storitvah
- function authenticate(options) {
- options = options || {};
- return async function(req, res, next) {
- console.log('start authenticate!');
- var request = new OAuth2Server.Request({
- headers: { authorization: req.headers.authorization },
- method: req.method,
- query: req.query,
- body: req.body
- });
- var response = new OAuth2Server.Response(res);
- try {
- let token = await oauth.authenticate(request, response, options);
- // Request is authorized.
- console.log('authenticate middleware: ' + JSON.stringify(token));
- if (options.role) {
- if (options.role != token.role) {
- throw new Error('User role error!');
- }
- }
- req.user = token;
- next();
- } catch (err) {
- // Request is not authorized.
- res.status(err.code || 500).json(err);
- // lahko tudi kličeš next, vendar bo req.user = undefined
- // req.user moraš potem preverjati v REST storitvah, ki jih želiš zaščititi
- }
- };
- }
- // uporabnik mora podati bearer token in imeti scope read
- // authenticate middleware lahko damo na cel /api, kot je v tem primeru, ali pa na posamezno metodo
- /*app.use('/api/free', apiFree);
- app.use('/api/paid', authenticate({scope:"read"}), apiPaid);
- app.use('/api/admin', authenticate({scope:"read"}), apiAdmin);*/
- router.get('/novice/free', apiPost.free);
- router.get('/novice/paid', authenticate({ scope: 'read' }), apiPost.paid);
- router.post('/novice/paid', authenticate({ role: 'admin' }), apiPost.addPost);
- router.post(
- '/novice/comment/:id',
- authenticate({ scope: 'write' }),
- apiPost.addComment
- );
- router.post(
- '/novice/update/:id',
- authenticate({ role: 'admin' }),
- apiPost.updatePost
- );
- app.use('/api', router);
- // error middleware vrača nek status, če prejšnji middleware kliče next(err) namesto res.send("")
- app.use((err, req, res, next) => {
- res.status(400).send({ error: err });
- });
- app.listen(process.env.port || 3000, () => {
- console.log('listening on port 3000');
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement