Skip to content

Instantly share code, notes, and snippets.

@kobi
Last active July 18, 2022 13:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kobi/7c0b8196d8b585dcc62d71947f909342 to your computer and use it in GitHub Desktop.
Save kobi/7c0b8196d8b585dcc62d71947f909342 to your computer and use it in GitHub Desktop.
NodeJs and OAuth2 - Updated example of using express-oauth-server with a memory model
var bodyParser = require('body-parser');
var express = require('express');
var OAuthServer = require('express-oauth-server');
const MemoryStore = require('./inMemoryModel.js')
const memoryStore = new MemoryStore()
var app = express();
// https://github.com/oauthjs/express-oauth-server#readme
// https://www.npmjs.com/package/express-oauth-server
app.oauth = new OAuthServer({
//app.oauth has 'authenticate', 'authorize', 'constructor', 'token'.
model: memoryStore, // See https://github.com/oauthjs/node-oauth2-server for specification
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//app.use(app.oauth.authorize());
//returns access toekn atter successful authentication.
app.post('/oauth/token', app.oauth.token());
app.get('/secret', app.oauth.authenticate(), function(req, res) {
// Requires a valid access_token.
res.send('Secret area');
});
app.get('/public', function(req, res) {
// Does not require an access_token.
res.send('Public area');
});
const port = 3000;
app.listen(port, ()=>console.log(`listening to port ${port}`));
// based on https://github.com/oauthjs/express-oauth-server/blob/master/examples/memory/model.js
/**
* Constructor.
*/
function InMemoryCache() {
this.clients = [
{
clientId : 'dummy-client-id',
clientSecret : 'dummy-client-secret',
redirectUris : [''],
grants: ['client_credentials'],
}];
this.tokens = [];
this.users = [{ id : '123', username: 'thomseddon', password: 'nightworld' }];
}
/**
* Dump the cache.
*/
InMemoryCache.prototype.dump = function() {
console.log('clients', this.clients);
console.log('tokens', this.tokens);
console.log('users', this.users);
};
/*
* Get access token.
*/
InMemoryCache.prototype.getAccessToken = function(bearerToken) {
//console.log('called getAccessToken, bearerToken=', bearerToken);
var tokens = this.tokens.filter(function(token) {
return token.accessToken === bearerToken;
});
return tokens.length ? tokens[0] : false;
};
/**
* Get refresh token.
*/
InMemoryCache.prototype.getRefreshToken = function(bearerToken) {
//console.log('called getRefreshToken, bearerToken=', bearerToken);
var tokens = this.tokens.filter(function(token) {
return token.refreshToken === bearerToken;
});
return tokens.length ? tokens[0] : false;
};
/**
* Get client.
*/
InMemoryCache.prototype.getClient = function(clientId, clientSecret) {
//console.log(`called InMemoryCache.getClient - clientId=${clientId}, clientSecret=${clientSecret}`);
var clients = this.clients.filter(function(client) {
return client.clientId === clientId &&
client.clientSecret === clientSecret;
});
//console.log('found clients: ' + clients.length);
return clients.length ? clients[0] : false;
};
/**
* Save token.
*/
InMemoryCache.prototype.saveToken = function(token, client, user) {
//console.log('called saveToken', arguments);
var newToken = {
accessToken: token.accessToken,
accessTokenExpiresAt: token.accessTokenExpiresAt,
clientId: client.clientId,
refreshToken: token.refreshToken,
refreshTokenExpiresAt: token.refreshTokenExpiresAt,
userId: user.id,
//these are required in /node_modules/express-oauth-server/node_modules/oauth2-server/lib/models/token-model.js
client: client,
user:user,
scope: null, //where are we taking scope from? maybe client?
};
this.tokens.push(newToken);
return newToken;
};
/*
* Get user.
*/
InMemoryCache.prototype.getUser = function(username, password) {
var users = this.users.filter(function(user) {
return user.username === username && user.password === password;
});
return users.length ? users[0] : false;
};
InMemoryCache.prototype.getUserFromClient = function(){
//console.log('called prototype.getUserFromClient', arguments);
//todo: find correct user.
return this.users[0];
}
InMemoryCache.prototype.saveAuthorizationCode = function(){
console.log('how is this implemented!?', arguments);
}
/**
* Export constructor.
*/
module.exports = InMemoryCache;
// C# client example, using RestSharp.
public string GetAccessToken()
{
var client = new RestClient("http://localhost:3000/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("scope", "datacapture.external.vendor");
request.AddParameter("client_id", "dummy-client-id");
request.AddParameter("client_secret", "dummy-client-secret");
var response = client.Execute(request);
ValidateResponse(response);
//todo: extract access token from JSON response.
return response.Content;
}
public string GetSecretContent(string url, string accessToken)
{
var client = new RestClient("http://localhost:3000");
var request = new RestRequest("/secret");
request.AddHeader("Authorization", "Bearer " + accessToken);
var response = client.Execute(request);
ValidateResponse(response);
return response.Content;
}
private static void ValidateResponse(IRestResponse response)
{
if (response.ErrorException != null)
{
throw new Exception("Bad", response.ErrorException);
}
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception("Status is not OK: " + response.StatusCode + " " + response.ErrorMessage + "\n\n" +
response.Content);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment