Giter Site home page Giter Site logo

oauth-example's Introduction

  ___    _         _   _       ____    ___  
 / _ \  / \  _   _| |_| |__   |___ \  / _ \
| | | |/ _ \| | | | __| '_ \    __) || | | |
| |_| / ___ \ |_| | |_| | | |  / __/ | |_| |
 \___/_/   \_\__,_|\__|_| |_| |_____(_)___/

 _____                           _      
| ____|_  ____ _ _ __ ___  _ __ | | ___
|  _| \ \/ / _` | '_ ` _ \| '_ \| |/ _ \
| |___ >  < (_| | | | | | | |_) | |  __/
|_____/_/\_\__,_|_| |_| |_| .__/|_|\___|
                          |_|           

Table of Contents

  1. Installation and Setup
  2. Important Links
  3. Oauth2.0 Things to Know
  4. Flows
  5. Database
  6. URL Queries

Installation and Setup

  1. Clone this Repo
  2. cd into the project root folder, and run yarn
    • If yarn is not installed, install it and then run yarn
  3. Run yarn authServer to boot up the oauth 2.0 server
  4. Run yarn devAuth to boot up the oauth 2.0 server in dev mode. This will enable hot reloading when your code changes.
  5. Run yarn test to run unit tests that cover all implemented grants
    • For verbose output, modify level in auth/tests/setup.js to be DebugControl.levels.ALL

back

Important Links

Checkout Oauth-server-github if you are running into any weird errors. Tutorials are seriously lacking on this implementation of the Oauth2.0 protocol as most people use an external service for it. Luckily, the errors are pretty specific, so you can go through their code to figure out what is happening.

Also, if you want to see how the middleware is generated, checkout this to see the middleware stuff. Their examples are out of date, so ignore them.

back

Things To Know

OAuth has a few parameters that are important to understand. Here is a list of good things to know:

State

State is an optional string provided by the client. It helps the client to protect against Cross Forgery requests and should not be used to transmit private data as it may be openly exposed and changed.

Scope

Flow

First, some definitions and reminders:

  • Client: The application wanting to have access to your resources
  • User: The person wanting to use your resources on the Client
  • Authorization: The process of determining whether something has access to protected resources
  • Authentication: The process of determining a person's identity.
  • OAuth2.0: A protocol outlining how authorization should happen. It is NOT an authentication library. You will need to provide that yourself.

Each of the grants provide a token which enables the user to access resources like the following diagram shows:

  1. Token is passed up in the authorization header
  2. Oauth Server validates the token
  3. Protected Resources are sent back down

Protected Resources

back

Authorization Code Grant

0. Overview

Aight, with those out of the way, we need to cover the basic flow with the authorization code grant.

  1. Authorization
    • Client application contacts the Server and requests access
    • Client application provides a client_id (unique string identifier)
    • Client provides a redirect uri to send the user after the code is delivered
    • Client may provide user data for authentication purposes
    • Server validates information and sends back an authorization code
  2. Token
    • Client uses received authorization code to request a token
    • Client sends client_id, client_secret (if applicable)
    • Server validates request, and sends a token.
  3. Authentication
    • Client uses token to gain access to Server's protected resources

Authorization Code Grant Flow

In the OAuth2.0 library, each of the above areas are handled within dedicated urls. Specific details on how to handle the different things are added to the model object within the OAuth server.

Now, we will explore each of the above 3 areas in depth.

back

1. Authorization

After hitting the Authorization url, the following calls are made within the model object in this order:

  1. getClient: This will extract the client_id from the request's query or body parameter. You can then go through and verify that the client is indeed a good client, what redirects are permitted for the Client, and what grants they have access to (in this example, just 'authorization_code'). Upon verification, return a valid Client object.
    • After calling getClient, if you passed an authenticateHandler to the authorize method call, this will then be called. If you return some non-falsy object, that object will be the User and will assume the User was able to authenticate. If you return a falsy object, we will assume that the user failed to authenticate, and must be booted. So, in short, this is where you authenticate the user.
  2. saveAuthorizationCode: This will give you an authorization code, the retrieved Client Object from getClient, and the user from the authenticateHandler. This information needs to be stored in your database. Once stored, return the information

After making the above calls, the server redirects you to the provided redirect_uri with the authorization code present as a url query parameter.

back

2. Token

After hitting the token url, the following calls are made within the model object in this order:

  1. getClient: Same as before, but will now allow you set the client_secret to ensure the client is a valid client.
  2. getAuthorizationCode: using the authorizationCode the client provides, look up in the database for the client, user, and code information for that code, and return it. If none, return false to stop the request as it is invalid.
  3. revokeAuthorizationCode: using the authorizationCode the client provides, delete from the database where the code exists. Return true if the code was deleted, false otherwise. Each authorization code can only be used once.
  4. generateAccessToken (optional): using the client and user provided, generate an access token. If not provided, the library will use its in-built library to generate a token. If you want to use JWTs, this is where that would happen.
  5. saveToken: using the client, code, and token generated earlier, save this information in the database.

The token is then sent as a json response like this:

{
  access_token: "38a72b9262f931a74377dc4f8c0d1d906a89af35",
  token_type: "Bearer",
  expires_in: 86399
}

back

3. Authentication

Use the token type and token code to add an authorization header like this: ${token_type $token_code}. This will allow the token to be transmitted securely.

After hitting an authenticate url, the following calls are made within the model object in this order:

  1. getAccessToken: using the token code provided by the client, return the token, client, and user associated with the token code. If not valid, return false.

If you want to access this information in your routes, it is found in res.locals.oauth.token, so you immediately have access to the client and user information associated with the token.

back

Refresh

Overview

The refresh token flow is one of the simplest of the grants. After any successful grant flow is completed and a token is generated, a refresh token is created along-side. If the refresh token is then returned with the other information, the client will be able to use the refresh_token with its client_id, client_secret, and grant_type of refresh_token in a post to the /token route to get access to a new valid token.

Refresh Token Gran

Database

There are four tables that should be stored in the database:

  • Client
  • User
  • Authorization Code
  • Token

The server will make use of the stored value in these for authorization and authentication purposes. Ideally, the database system used would be promise-based such that they can just be returned. If this is not available, you can make use of the callback parameter in each of the model functions.

back

Client

This stores information on the client.

  • id: unsigned long primary key auto_increment. // For Relations
  • client_id: String unique // Client knows
  • client_secret: String // Client knows
  • data_uris: [String] // Array of acceptable redirect locations
  • grants: [String] // Array of grants client has access to (authorization_code being one)

back

User

This stores information about the user.

  • id: unsigned long primary key auto_increment. // For Relations
  • Anything else you want / need for your server

back

Authorization Code

This stores information related to the authorization code

  • authorization_code: String primary key // string with a valid code
  • expires_at: Date // When the code expires
  • redirect_uri: String // String with a valid uri
  • client_id: unsigned long references Client(id)
  • user_id: unsigned long references User(id)

back

Token

This stores information related to your tokens

  • access_token: String primary key // string with a valid access token
  • access_token_expires_at: Date // When token expires
  • client_id: unsigned long references Client(id)
  • user_id: unsigned long references User(id)

back

URL Queries and Formatting

Once everything is set up the way you want it, you are ready to start making requests to the server. As a reminder, there are three categories of requests that are possible:

  1. Get Authorization Code
  2. Get Token
  3. Get Access to Protected Resource

This section will outline how each of these requests ought to be formatted to successfully go through.

back

Authorization Code

The request for an authorization code requires the following information:

  • client_id // The unique string identifying a client
  • redirect_uri // The place to redirect after receiving the code
  • response_type // what the client is expecting. Should be code

These parameters can be included within the body of a POST request, or be sent as URL Query Parameters like this: /request/authorization?client_id=<ID>&redirect_uri=<URL>&response_type=code

You can additionally send up other information to help validate the user within the authentication handler.

You know this has handled things successfully when you redirect to the uri you provided.

back

Token

The request for an access token requires the following information:

  • client_id // Unique string of client
  • client_secret (if applicable) // client secret key
  • grant_type // authorization_code in this example

The request should additionally have the following header:

'Content-Type': 'application/x-www-form-urlencoded'

and the data should be provided within the body of a post request.

This will send back a json response as outlined earlier.

back

Access Protected Resource

Requesting access to protected resources consists of making the request as usual, but adding the following header:

{
  Authorization: `${tokenType} ${token}`,
}

with the tokenType and token coming from the json response in the token request.

back

oauth-example's People

Contributors

14gasher avatar jaynarw 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

oauth-example's Issues

Add Authorization landing page example

Firstly, I just want to say thank you for your hard and sharing this with us. It's helped me understand the flow of using authorization codes in node-oauth2-server a lot better than the official documentation.

I was wondering whether you would be open to the idea of adding an example of how to implement an authorization landing page, where the user is prompted to make a decision on whether or not to grant the client's request.

Much appreciated.

Fix generateAuthorizationCode without editing library

Just open model.js on line 111 change function to:

` generateAuthorizationCode: (client, user, scope,cb) => {

log({
  title: 'Generate Authorization Code',
  parameters: [
    { name: 'client', value: client },
    { name: 'user', value: user },
  ],
})

const seed = crypto.randomBytes(256)
const code = crypto
  .createHash('sha1')
  .update(seed)
  .digest('hex')
cb(null,code)

},`

Authentication example

Authentication is not supported out of the box with OAuth library.

The flow needs to look like this:

  1. Client redirects user to auth server
  2. Authentication
    a. If user enters false information, server kicks them back to the form
    b. Otherwise, server passes request on to authenticate middleware
  3. Continue as normal

Let's implement this as a middleware looking approximately like this:

const checkIfValid = (req,res,next) => {
  if(validUser) return next()
  return formWithBadInfoErrorInQueryParams
}
router.post('/fromAuthForm', checkIfValid, oauthJunk)

Authenticate

The oauthServer.authenticate() doens't care about the token at all...
Even if you pass an invalid token, the request will be authorized.

Any thoughts?

Edit:

found it, the getAccessToken missed a db check

Token

not able to call oauth/token on redirect uri.

Tests failing

Steps to repro:

  • Clone the repo
  • run npm install
  • run npm test

Include Sqlite

To better understand how all of this stuff connects together, include sqlite to demonstrate how the db relates. This will allow us to demonstrate bad clients / users.

Demo times out on redirect to /oauth/authorize

I'm trying to test the demo to understand the flow - the /oauth form submission passes values into the server but the server process never resolves and the redirect to /oauth/authorize eventually times out. This is the final output of the dev server:

Screen Shot 2019-11-19 at 2 33 28 PM

All but 3 of the included tests are also failing due to timeouts or 400s.

Any help would be appreciated!

model issue

I created the models as you created but when I am assigning the model to the OAuth model its showing error. (i am developing in typescript). when I run your code I am not getting any response after submitting the client credentials and user details.
here are my code sample

export const oauthConfiguration = new oauthServer({
model: oauthModel,(here i am getting error when i am assiging)
accessTokenLifetime: 60 * 60 * 24, // 24 hours, or 1 day
allowEmptyState: true,
allowExtendedTokenAttributes: true
});

Wrong error message when invalid request for password grant

When I request an access token with 'password' grant and requireClientAuthentication to false.
If 'grant_type' parameter is missing or invalid, I got the folowing error message:

{
    "error": "invalid_client",
    "error_description": "Invalid client: cannot retrieve client credentials"
}

But we should receive the following error messages:

//For missing grant type
{
    "error": "invalid_request",
    "error_description": "Missing parameter: `grant_type`"
}
//For invalid grant type
{
    "error": "unsupported_grant_type",
    "error_description": "Unsupported grant type: `grant_type` is invalid"
}

The cause:
Module call 'getClientCredentials' before grant type verification.
And during this test

if (!this.isClientAuthenticationRequired(grantType))

isClientAuthenticationRequired function return true, which implies a client verification, via client id and client secret.
And as in this case, only the 'client_id' is provided, this causes the error to return 'invalid_client'

best regards.

Should update readMe and code

When creating this server, I had an issue with token creation when calling getAuthorizationCode where my console would say something along the lines of "InvalidRequest: redirect_uri is not a valid URI". I did some digging and found that this is because the request for a token must include the redirect_uri in it, and this is verified by a comment included at node_modules\express-oauth-server\node_modules\oauth2-server\lib\grant-types\authorization-code-grant-type.js on line 126 which reads:

"The authorization server MUST ensure that the redirect_uri parameter is present if the redirect_uri parameter was included in the initial authorization request as described in Section 4.1.1, and if included ensure that their values are identical."

To fix this, I made sure that our client sent this by including
const redirecturi = 'http://localhost:3030/client/app'
and editing line 39 to be
body: code=${code}&client_secret=${secret}&client_id=${id}&grant_type=authorization_code&redirect_uri=${redirecturi}

image
image

solved bugs in your code

I solved the bugs in your code according to the new latest version. how to give push requests to your repo.

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.