Giter VIP home page Giter VIP logo

oauth2orizerecipes's Introduction

OAuth2orizeRecipes

Build Status

OAuth2 security recipes and examples based on OAuth2orize.

The express2 example from OAuth2orize is a great and simple minimal OAuth2 Server in Node.js. It is an example you can use to get an idea of how to write your own OAuth2 Server in Node.js. The recipes here are built from it and are more complete but also a bit more complex.

Sign In

You can see a demo of it in action here

Installation

git clone https://github.com/FrankHassanabad/Oauth2orizeRecipes.git
cd Oauth2orizeRecipes/authorization-server
npm install
npm start

Go here for how to use the REST API
https://github.com/FrankHassanabad/Oauth2orizeRecipes/wiki/OAuth2orize-Authorization-Server-Tests

Go here for high level views of security scenarios
https://github.com/FrankHassanabad/Oauth2orizeRecipes/wiki/Security-Scenarios

See the curl folder for headless operations and ad-hoc testing
authorization-server/curl/README.md

Features of the Authorization Server

  • All 4 grant types exposed out of the box
  • Access/Refresh Tokens
  • All Tokens are JWT based tokens
  • Configurable expiration times on tokens
  • Single Sign On (SSO) Example
  • Example of trusted clients
  • REST tokeninfo endPoint for verifying a token is valid.
  • REST revoke endPoint for revoking either an access token or a refresh token.
  • Authorization tokens are only useable once and are short expiring JWT tokens
  • Full tokens are NOT stored in the DB since they are JWT signed tokens. Only ID's of tokens are stored.
  • SSL/HTTPS usage
  • Unit and Integration tests of the majority of code and OAuth2 flows
  • More complex UI Examples for the Sign In/Login and the Decision Screens

oauth2orizerecipes's People

Contributors

0xgeert avatar frankhassanabad avatar gswalden avatar hygkui avatar idangozlan avatar johnmclear avatar jrmlstf avatar mlersch avatar rdsubhas avatar yunusd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oauth2orizerecipes's Issues

Probably a bug with passport

If you add latency (as would exist in a production environment) to your database the authorization fails in your tests:

Add the latency to every db function like this:
exports.find = function (key, done) {
setTimeout(function(){
var token = tokens[key];
return done(null, token);
},300);
};

How to validate Redirect URLs?

Hi, Thanks so much for this wonderful demo. But right now, Clients are accepting any redirect URL, which is a huge problem (especially with implicit authorization).

Can you provide some tips/pointers on how to validate Redirect URLs? i.e. Each client has a list of allowed Redirect URLs, and authorize dialog requests must redirect to only those URLs. I tried, but couldn't find the right place to put this check...

MongoDB

When setting up the example for using MongoDB the following error makes node crash:

http.js:1178
var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' +
^
TypeError: Cannot call method 'toString' of undefined
at ServerResponse.writeHead (http.js:1178:45)

Where to store scopes?

Hello,
I am confused on where to store scopes for oauth.
For now I have stored scopes in a table in database. and when users point to oauth dialog link with scopes params I read them from database and show dialog.
However In below code in file https://github.com/FrankHassanabad/Oauth2orizeRecipes/blob/master/authorization-server/oauth2.js
In grant code function you have set scope to auth code from client.scope. Is not scope to be available from ares?
server.grant(oauth2orize.grant.code(function (client, redirectURI, user, ares, done) { var code = utils.uid(config.token.authorizationCodeLength); db.authorizationCodes.save(code, client.id, redirectURI, user.id, client.scope, function (err) { if (err) { return done(err); } return done(null, code); }); }));
Do we need to store scope in client table?

Generate a token for UUID for an iOS app in oauth2orize

We are using oauth2orize as our authentication server. We need to generate a token for an iOS app for its UUID/GUID. There is no default grant type for this.

Many people say to create our own grant type by using GrantTypeInterface.

The idea is something like this:

  1. Create a guest user with Uuid and return a token.
  2. Guest user can convert to customer user by registering himself.

are we doing/thinking this incorrectly?

https://localhost:3000/oauth/token 403 (Forbidden)

hi, i'm trying to integrate "authorization-server" to meteor

but i get this after click "Submit Post"

{"error":"invalid_grant","error_description":"Invalid authorization code"}

POST oauth/token HTTP/1.1
Host: https://localhost:3000
Content-Type: application/x-www-form-urlencoded

code=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZGIxNjY2NS01ZjJmLTQxYzgtYmRmNy0wNzM5NzQxN2JmN2UiLCJzdWIiOiIxIiwiZXhwIjoxNDg3MjE5NzczLCJpYXQiOjE0ODcyMTk0NzN9.aUZQJGgeRSGRzEpQlDI_KZrt6sC7dd8HdxSSRBM9RQR1hkjOxWW6CLjs_c2rMhnauLSNMS68xzOUD8OlZJ5CEXuO93G1vG0CxbnNXlzqOACGzPHdcYY8ka_1vXBm5u-1vS7Y1hR2NoUo6IL5q3xyPKKU1nULhGQ3H4AvEcSJDggnexLGz5ccf4nOhWuJns3WKBqx9vxhG0gWMChz9IyF1EhJicdMnk4a-4mq77xAmAKez0h8E-Q9y7OYB6uroam6vovegfWvx2bDgRqWLDKMCxXJuxJQIBjXt6vMqh6sCXenT13jZalzVXqfQdyOE0inVkC5brFs0YGyvvL3blzomg&
redirect_uri=https://localhost:3000&
client_id=abc123&
client_secret=ssh-secret&
grant_type=authorization_code

ReferenceError: Invalid left-hand side in assignment in utils.js

Hello,

I have it successfully installed, but by starting node app.js, I get this error message in the terminal:

/authorization-server/utils.js:24
exports.createToken = ({ exp = 3600, sub = '' } = {}) => {
^

ReferenceError: Invalid left-hand side in assignment
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:373:25)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at Object. (/var/www/virtual/xxx/xxx.xxx.de/authorization-server/oauth2.js:15:21)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)

What is the reason for this issue?
I could only find that the issue could be related to = and == , but changing it doesnt brought help.

Hope for a answer
Thanks

trying to implement validations in login form

i am trying to implement validations for login form from below link.
https://truongtx.me/2014/03/29/authentication-in-nodejs-and-expressjs-with-passportjs-part-1/

as we are using mongdb for session, not able to do the clear message on GET call.

exports.loginForm = function (req, res) {
    console.log("in render");

  res.render('login',{ message: req.session.messages });
  // and then remember to clear the message
   req.session.messages = null;
  //**this line does not clear on next GET call**

};

exports.login = function (req, res,next) {
 // passport.authenticate('local', {successReturnToOrRedirect: '/', failureRedirect: '/login'})
//above line replaced with below code in 
 passport.authenticate('local',function(err, user, info) {
    console.log("in here");
    if (err) {
      // if error happens
      req.session.messages = info.message;
      return next(err);
    }

    if (!user) {
      // if authentication fail, get the error message that we set
      // from previous (info.message) step, assign it into to
      // req.session and redirect to the login page again to display
     // console.log("not in user");
      req.session.messages = info.message;
      return res.redirect('/login');
    }

    // if everything's OK
    req.logIn(user, function(err) {
      if (err) {
       //   console.log("error");
        req.session.messages = "Error";
        return next(err);
      }

      // set the message
      req.session.messages = "Login successfully";
      return res.redirect('/');
    });

  })(req, res,next)

  }; 

two issues i am facing are

  1. validation message does not clear on next GET call or refresh.
  2. console error in terminal
    TypeError: Cannot read property 'toString' of undefined express router layer
    look like this is big issue but not able to reproduce this again.

Authorization-Server 0 response when ran.

Hey Frank, finally today and tomorrow are the days I get to play and implement this code into our mega api..... however...

Authorization-server, I tried running the example code, which should work, it used to, but I am getting "0 response" in the REST client. No error showed up in the console either.

Regards

Thank you for taking the time explaining the differences between the strategies AND implementing them. I have implemented one of the strategies and modified the body to match my needs. Now, I am finalizing the tests and nothing really major is left.

If you please can review the code and suggest any extra modifications or structure improvements?

https://github.com/MohamadAtieh/node-endpoint

Thanks again!

Refresh Tokens

Hi there Frank. This is plaguing me for quite sometime, I do not understand how refresh tokens work. Can you give me an example, or a gist? How does it apply from the client side app?

I have a SPA AngularJS app, with no backend, using Oauth2 API server to communicate, so far, in pre-beta I have just been using really-long-lived tokens from Oauth2Orize, but now it's coming up to launch and I need to make sure I can do refresh tokens..

Think you can point me in the right direction, maybe even an example so I can better understand?

scopes

are you planning to tackle scopes?

Just wanted to know if you were or not, because if you were, Im not going to. (duplicating efforts)

Client Scope & AuthCode scope undefined when working with database

Hey,

first of all: thanks for documenting this so detailed. I went through a few oauth examples, and this one is definitely the best one.
Now to the issue I have:

I am busy connecting everything to a Database, and so far it works, except one thing: When a user authorizes a client, only an access token is sent, no refresh token. I narrowed this down to the fact that the validate.isRefreshToken() fails, because the scope is null. I am still busy trying to figure out where exactly scope becomes undefined, but here is what I have found so far:

In oauth2.js, the authorization middleware:

..
}), (req, res, next) => {
    // Render the decision dialog if the client isn't a trusted client
    // TODO:  Make a mechanism so that if this isn't a trusted client, the user can record that
    // they have consented but also make a mechanism so that if the user revokes access to any of
    // the clients then they will have to re-consent.
    db.clients.findByClientId(req.query.client_id)
    .then((client) => { ....
     // client.scope is undefined
     }

Here, the scope in the client object is undefined for me, however looking at the unmodified example which uses memory storage, it is properly defined. I tried manually defining it like such
client.scope = "offline_access" but that did not do the job, it gets lost somewhere later on.

What is more likely to be the problem is here in the same file:

server.grant(oauth2orize.grant.code((client, redirectURI, user, ares, done) => {
  const code = utils.createToken({ sub : user.id, exp : config.codeToken.expiresIn });
  db.authorizationCodes.save(code, client.id, redirectURI, user.id, client.scope)
  .then(() => done(null, code))
  .catch(err => done(err));
}));

Again, client.scope is undefined here. Any idea what the connection here might be, and how this can be tackled when working with a database? Which functions passes the client object to above function?

When I use:
db.authorizationCodes.save(code, client.id, redirectURI, user.id, "offline_access")
it works, the refresh_token gets sent as well, but that is only a temporary solution.
I though about having another column in the clients table saving the scope, however that is not a solution I would prefer.

Wrong Issue Token Logic for Access+Refresh Token?

Hey,

I stumbled across the following issue, where the application does not issue a refresh Token where it should.
Have a look at the following part in validate.js:

/**
 * Given an auth code this will generate a access and refresh token, save both of those and return
 * them if the auth code indicates to return both.  Otherwise only an access token will be returned.
 * @param   {Object}  authCode - The auth code
 * @throws  {Error}   If the auth code does not exist or is zero
 * @returns {Promise} The resolved refresh and access tokens as an array
 */
validate.generateTokens = (authCode) => {
  if (validate.isRefreshToken(authCode)) {
    return Promise.all([
      validate.generateToken(authCode),
      validate.generateRefreshToken(authCode),
    ]);
  }
  return Promise.all([validate.generateToken(authCode)]);
};

So, we only get a refresh token if the authCode provided is a refresh token. That doesn't make sense, right? A refresh token should make this issue only 1 (access) token, and an authorization code should make it issue 2 (access + refresh). It should be if (!validate.isRefreshToken(authCode)) if I understand the specification correctly.

Good job

I didn't tested your code yet, but this repository it's certainly enough to start with oauth2 (didn't had much luck with other resources about writing stuff with oauth*) and i just wan't to say GOOD JOB, Thanks! ;-)

OAuth2 with social network

Hello! Tell me how you can implement in the "authorization-server" log on using social networks? What does that require?

Automatic Authorization

Is there a way to authenticate users without the decisión?? (Screen where it ask the user to allow or not allow to access data).

Why did you send client_secret in Authorization code grant type?

This broken Authorization Code flow, because you cannot keep client_secret credential safe in the client, so.. why in your demo example (authorization code) did you send in the body request (x-www-form-urlencoded) the client_secret field or I mistaken.

Regards

Understanding Security Scenarios

In Basic Authentication, would you pls tell me about this following step:

Step 1, Send Basic auth user id and password with API call

GET product/API/endpoint HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

So you're sending the id & password via a GET call ? Where did you get the token czZCaGRSa3F0MzpnWDFmQmF0M2JW?

Refresh Token missing

When I request my "access token", by passing my "auth token", I was expecting to also receive a "refresh token", however it's missing.

Can someone explain why it's missing, and how I get hold of a refresh token?

This is what's returned...

access_token:
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwMWZkNWVkMi1mNzI0LTRhNzMtODUyNC01OWJhMDZiZjRlNTgiLCJzdWIiOjEsImV4cCI6MTUyMDAxMTA2NiwiaWF0IjoxNTIwMDA3NDY2fQ.2Yk9qz5smUWqNMlSwCvPXjHZzknun9wcP62fytVR1lof4tEjuYYKeEP_zb_A1dDYLpKhnBLFoW5Ama9pOrJkz77fJ_gVnemdR9LrrKof9xIAF9JemuYMroCjIawDWHIbiv9tmu4lAO-DIsA6EQnCYNXZX89ViZkuiMWEN1ER_6SPGofS-Ze07zDEFzQgBLrE5s3v-EGaz6CBczHPyCuFchZ7xnoZ_J3YnuP00PyDYwY5vv9xgPIsz_k0V9Hz3VVlcZu-2YjGxiLrRFgx2lhZP5jlKEI_Qs0_xMtyOE6972ck72CFEnqIxpiPUFRlN9s8f7jRBAnLkkFYh_e4H8FNeA"
expires_in:3600
token_type:"Bearer"

web-client can start with `node app.js`

 throw new TypeError('The super constructor to `inherits` must not ' +
          ^
TypeError: The super constructor to `inherits` must not be null or undefined.
    at Object.exports.inherits (util.js:728:11)
    at Object.<anonymous> (./node_modules/http-proxy/lib/http-proxy/index.js:111:17)

This problem was caused by the http-proxy, it need the version > 1.11.x
so change it to 1.13.2 will fix this.

Examples don't run

Installed the examples as instructed, but when Ioad them into the browser I get an "Error: no data received, ERR_EMPTY_RESPONSE". Any ideas why this might be happening?

RefreshToken endpoint sending malformed JSON

When sending a refresh token request like so

GET https://localhost:3000/oauth/token
Authorization: Basic YWJjMTIzOnNzaC1zZWNyZXQ=
grant_type=refresh_token&refresh_token=zBUPO4kd5EzIvJveX36fKXBrH82TwU4gxgJUdUbgCttWr6PHxq4ksjwVrJEOpH12GEfvhJVRFd5fX7oeI1kLFoubaRFoA12h9UoEXDXaBia9qE7lyvLqBeuPyZWA39OxrggQFHEx8liOWyZpdCK3QPu5pkXVZsAnN1BqrzsXxURZETTtuQZ8ZZOZ44Sias613osirhCKnnuX6f51Ds9id3TSPhUN7vS3tZC6NHPblDgnmlTZIiDE8nqpz4bR2HjP

The response being sent back is

{
"access_token":"ByrSwz2qzERjgmkr4P4PCaY4EqA45pA5mdyvlCWi9AQ3asPkTtFuTbMsVXxRPjq2gh8d2cqBz9A7i0pQAdH1818dHtHFnZei70OVHh0kUcHT1DJ4ZJ4PvUA3c5c8pavfGtJnfqJDbmIpVED3nxfEtKTcjY5P5tPDqNA548JwQISgsYsdYrCowEfTr9vaBlo0SpGrkqBVhRnIJBGFxllbCFxCw7j42clq5Oj6dtPU8UR5MWkCRMRl7uhWWIl6sQO7",
"refresh_token":{"expires_in":3600},
"token_type":"bearer"
}

Which is incorrect because of the odd "refresh_token" nested in there when it shouldn't be in there at all. Instead it should be

{
"access_token":"ByrSwz2qzERjgmkr4P4PCaY4EqA45pA5mdyvlCWi9AQ3asPkTtFuTbMsVXxRPjq2gh8d2cqBz9A7i0pQAdH1818dHtHFnZei70OVHh0kUcHT1DJ4ZJ4PvUA3c5c8pavfGtJnfqJDbmIpVED3nxfEtKTcjY5P5tPDqNA548JwQISgsYsdYrCowEfTr9vaBlo0SpGrkqBVhRnIJBGFxllbCFxCw7j42clq5Oj6dtPU8UR5MWkCRMRl7uhWWIl6sQO7",
"expires_in":3600,
"token_type":"bearer"
}

Storing on mongdb

Filled in config\index.js:
exports.db = {
timeToCheckExpiredTokens: 3600,
type: "mongodb",
dbName: "OAuth2orizeRecipeTokens"
};
exports.session = {
type: "MongoStore",
maxAge: 3600000 * 24 * 7 * 52,
//TODO You need to change this secret to something that you choose for your secret
secret: "A Secret That Should Be Changed",
dbName: "Session"
};

got this:
"D:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" "C:\Program Files\nodejs\node.exe" app.js
js-bson: Failed to load c++ bson extension, using pure JS version
{ [Error: Cannot find module '../build/Release/bson'] code: 'MODULE_NOT_FOUND' }
Using MongoDB for the Session
Using MongoDB for the data store
OAuth 2.0 Authorization Server started on port 3000

and no connection to my standard configured Mongo Database..

Debugged the system:

Set a breakpoint to
mongoinit.js

MongoClient.connect('mongodb://127.0.0.1:27017/' + config.db.dbName, function (err, db) {

but it dont comes to it...

Any idea whats happening hear.

If I put it back to memory based store everything works fine...

Oh I forgot I have updated last changes in the authorization server...

(refreshtoken,authorizationcodes,package)

oauth2 authorization code client implementation with react router ?

Hi,
we have created our own oauth 2 server with authorization code implementation from this code base.

but we are trying to integrate oauth2 client authentication in web application which includes react router and flux implementation.

we looked into many git repositories but not getting any proper way to do this.

is there any implementation which points us to how it can be achieved?

Thanks again.

OAuth2 User Login vs. Client Concerns

First, thanks you so much @FrankHassanabad for all of the work that you've displayed on this project. I don't think any other resource could have explained how OAuth2 works with better clarity, so thank you for that.

I do have some questions however, that I'm hoping you wouldn't mind clearing up for me if your not too busy.

The client. I understand the concept from a broad perspective, as a model that represents the different devices that may want to access a user's data. So if I have a Android application that is looking to pull resources that a certain user is privy to, the Android device would be the client in this particular case.

I start to get a little fuzzy when talking about implementations from a browser perspective. If I have a SPA on the browser, that is looking to signup / login for the first time, what is the protocol in such a case for the client id?

In our particular case, we have a redux application that's looking to authenticate. The user logs in, which has been shown on you're application, and is given a session. The unclear part is how the client is created.

I'm under the assumption currently that the each user should have it's own client for the browser SPA. In the browser context, is it safe to just create a client when the user is registered, that has full permissions? Or is it the other way around, where the client is hardcoded and the user receives an access_token based on that hardcoded client?

Bryce Jacobs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.