Last active
July 18, 2022 13:05
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}`)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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