GithubHelp home page GithubHelp logo

oauthinaction / oauth-in-action-code Goto Github PK

View Code? Open in Web Editor NEW
685.0 44.0 517.0 3.08 MB

Source code for OAuth 2 in Action

Home Page: https://www.manning.com/books/oauth-2-in-action

License: Other

JavaScript 55.64% HTML 44.27% CSS 0.09%

oauth-in-action-code's Introduction

OAuth 2 in Action

Cover of OAuth 2 in Action

https://www.manning.com/books/oauth-2-in-action

About the book

Think of OAuth 2 like the web version of a valet key. This HTTP-based security protocol allows the users of a service to enable applications to use that service on their behalf without handing over full control. Web and mobile apps can securely access information from other servers for these users, enabling you to give your users functionality and services from other sites. Instead of unsafe password-sharing, OAuth offers a much more secure delegation protocol. OAuth is used everywhere, from large providers like Facebook and Google, to small APIs at startups, and even cloud services, it’s the worldwide standard. OAuth 2 is the must-know security protocol on the web today.

OAuth 2 in Action teaches you practical use and deployment of this protocol from the perspective of a client, authorization server, and resource server. You’ll begin with an overview of OAuth and a look at its components and interactions. Then, using lots of hands-on examples, you’ll build your first OAuth client, followed by an authorization server, and then a protected resource. The second part of the book dives into crucial implementation vulnerability topics. Then you learn about tokens, dynamic client registration, and more advanced topics. This book teaches you to how to distinguish between different OAuth options and choose the right set for your application. By the end of this book, you’ll be able to build and deploy applications that use OAuth on both the client and server sides.

About the authors

Justin Richer is a systems architect, software engineer, standards editor, and service designer working as an independent consultant. Antonio Sanso works as Security Software Engineer, he is a vulnerability security researcher and an active open source contributor.

How to Install and Run the Project

Clone Repository

Using terminal go to directory of your choosing and execute git clone https://github.com/oauthinaction/oauth-in-action-code.git

Install Dependencies

Repository contains multiple project, each requiring to install its dependencies before executing any code. For each exercise, enter the directory and run npm install to install dependencies before executing the code.

Run Project

To execute any file written in JavaScript using node simply run node [file_name] in terminal for eg. node client.js.

Some examples require to run multiple files concurrently to work properly (for example, the authorization server, client, and resource server components), and it is recommended that each file be executed in its own separate environment, such as in separate terminal windows.

Each service runs on localhost and is usually available over HTTP.

The usual ports for items is:

  • client.js - http://localhost:9000/
  • authorizationServer.js - http://localhost:9001/
  • protectedResource.js - http://localhost:9002/

oauth-in-action-code's People

Contributors

anturgyffrous avatar asanso avatar caodangtinh avatar cm-iwata avatar joostd avatar jricher avatar mkontani avatar mousedownmike avatar pardeep-singh avatar seriousm avatar task4233 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oauth-in-action-code's Issues

nosql.one() expects a callback and gets 'undefined'

I've started the tour through "OAuth 2.0 in Action" and begun the exercises in chapter 3. At the end of chapter 3.3 and at the start of chapter 3.4, I've tried to get a protected resource from the server in 'protectedResource.js'. The server crashed, if it tries to call 'nosql.one(..., ...)' with the following error-message:

OAuth Resource Server is listening at http://127.0.0.1:9002
Incoming token: 987tghjkiu6trfghjuytrghj
fs.js:156
throw new ERR_INVALID_CALLBACK(cb);
^

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined

Express middleware over-writing headers

The Express middleware sets headers automatically, so code like this gets overwritten:
var headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + encodeClientCredentials(client.client_id, client.client_secret)
};

var tokRes = request('POST', authServer.tokenEndpoint, {	
		body: form_data,
		headers: headers
});

If you check what's actually in the headers of tokRes you'll see something like:
Headers: { 'x-powered-by': 'Express',
'content-type': 'application/json; charset=utf-8',
'content-length': '33',
etag: 'W/"21-occYTPXPStEvVz6I6gFNf+WJ+pg"',
date: 'Thu, 21 Jun 2018 23:43:03 GMT',
connection: 'close' }

This basically makes it impossible to pass client_id, client_secret in headers.

Missing comma in book code example

"3.3.2 Processing the authorization response"
...
"Our final function for this part of the OAuth client looks like this:"
...
Missing comma in the code example for the headers

ch-4-ex-1

I cannot obtain the protected resource based on the current setup.
Following app.get("/fetch resource") router I get back the console.log message: Making request with access token OzH6eSierpbDo7YaeFcp861YmvHKBTPf, but I get the error view with a code of 401
The resource object resulting from the post request to app.post("/resource") router is as follows:

Response {
  statusCode: 401,
  headers:
   { 'x-powered-by': 'Express',
     'access-control-allow-origin': '*',
     date: 'Mon, 01 Jul 2019 20:19:43 GMT',
     connection: 'close',
     'content-length': '0' },
  body: <Buffer >,
  url: undefined }

It seems that the nosql.one function does not find the token in the database (as the incoming token message shows the value of the token) although if i inspect the nosql file the token is written on the file.
The docs for nosql seems very thin, i can find any help in them for solving the problem.

ch6-ex-1 code typo

Page 96 of the page shows:

nosql.insert({ access_token: access_token, client_id: clientId, scope: rscope });

Should be:
nosql.insert({ access_token: access_token, client_id: client.client_id, scope: rscope });

exercises/ch-6-ex-2/client.js accesses undefined variable

In line 44 of exercises/ch-6-ex-2/client.js, the code access refresh_token which is not declared or used.

The following

app.get('/', function (req, res) {
	res.render('index', {access_token: access_token, refresh_token: refresh_token, scope: scope});
});

should become

app.get('/', function (req, res) {
	res.render('index', {access_token: access_token, scope: scope});
});

I will be happy to put in a PR for this

auth server not robust against bad basic auth

if a client fails to send the text 'Basic' at the beginning of the auth header, the auth server code isn't smart enough to treat that as a bad request and tries to look up the client anyway.

ch-3-ex-1 and ch-3-ex-2 throws: TypeError [ERR_INVALID_CALLBACK]: Callback must be a function

When running the exercises with the complete client code (client.js), fetching the token works, but when trying to request the protected resources, an error is thrown on the protectedResources server:

$ node protectedResource.js 
OAuth Resource Server is listening at http://127.0.0.1:9002
Incoming token: 4ZYxN6lwg71yGIDb5UoOIlqdcNEqL8To
fs.js:144
    throw new ERR_INVALID_CALLBACK();
    ^

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
    at makeCallback (fs.js:144:11)
    at Object.close (fs.js:399:20)
    at next (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/nosql/index.js:2388:8)
    at /home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/nosql/index.js:2413:4
    at FSReqCallback.wrapper [as oncomplete] (fs.js:478:5)

causing the client to throw:

Error: socket hang up
    at doRequest (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/sync-request/index.js:31:11)
    at /home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/client.js:127:17
    at Layer.handle [as handle_request] (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/layer.js:95:5)
    at /home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:335:12)
    at next (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:275:10)
    at expressInit (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/middleware/init.js:40:5)
    at Layer.handle [as handle_request] (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:317:13)
    at /home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:335:12)
    at next (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/router/index.js:275:10)
    at query (/home/myuser/Projects/oauth-in-action-code/exercises/ch-3-ex-2/node_modules/express/lib/middleware/query.js:45:5)

Using:

node 11.1.0
npm 6.4.1

ch-3-ex-1 protected resource not working (ERR_INVALID_CALLBACK)

I tried working through Chapter 3 Exercise 1. I copy and pasted the code for the client from the appendix. I notice the code for the authorization server and protected resource appears to be completely filled in already, so I didn't make any changes to that code. However, at the end of the exercise when I get a token and then click Get Protected Resource, I get the following error message in the terminal for my protected resource server:

node .\protectedResource.js
OAuth Resource Server is listening at http://127.0.0.1:9002
Incoming token: xmFD2F9vg6AF4tQGLIzX19Vm27gI426K
fs.js:142
    throw new ERR_INVALID_CALLBACK();
    ^

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
    at makeCallback (fs.js:142:11)
    at Object.close (fs.js:400:20)
    at next (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\nosql\index.js:2388:8)
    at C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\nosql\index.js:2413:4
    at FSReqCallback.wrapper [as oncomplete] (fs.js:479:5)

Throughout this process, the following appears in the terminal for the client server. It appears to have no problem getting the authorization code and then the access token. The logs say it begins to make the request for the protected resource with an access code:

node .\client.js
OAuth Client is listening at http://127.0.0.1:9000
redirect http://localhost:9001/authorize?response_type=code&client_id=oauth-client-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&state=uaupQrqmFN8xKZzps0WT8YgSxdGeNJQR
Requesting access token for code 7ZsNkiot
Got access token: 11zLkASTHepVKxWQ7lClBAEX8iWYcFRs
(node:8588) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
Making request with access token 11zLkASTHepVKxWQ7lClBAEX8iWYcFRs
Error: read ECONNRESET
    at doRequest (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\sync-request\index.js:31:11)
    at C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\client.js:120:17
    at Layer.handle [as handle_request] (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\layer.js:95:5)
    at C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:275:10)
    at expressInit (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\middleware\init.js:40:5)
    at Layer.handle [as handle_request] (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:317:13)
    at C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\router\index.js:275:10)
    at query (C:\Users\mattw\repos\oauth-in-action-code\exercises\ch-3-ex-1\node_modules\express\lib\middleware\query.js:45:5)

A portion of this error appears in my web browser too - the part that begins with Error: read ECONNRESET.

ch-3-ex-2authorizationServe.js bug

I have to introduce some time gap between nosql.clear() and nosql.insert(), like below:
// clear the database on startup
nosql.clear();
// inject our pre-baked refresh token
setTimeout(() => nosql.insert({ refresh_token: 'j2r3oj32r23rmasd98uhjrk2o3i', client_id: 'oauth-client-1', scope: 'foo bar' }), 5000)

Does anybody know why? Is there any better way to fix this?

nosql causes exceptions in Node.js > v10.0.0

nosql will cause an exception in FileReader.prototype.open line 2388 will cause an exception in Node.js > v10.0.0. The callback parameter is no longer optional for fs.close. Not passing it will throw a TypeError at runtime. There was a depreciation warning since Node.js v7.0.0. My workaround for now is to change fs.close to fs.closeSync in line 2388 of the index.js file in node_modules/nosql. The author has indeicated that he will be making changes to the module soon. Refer to petersirka/nosql#46

First character of token gets truncated when parsed by protected resource

inToken = auth.slice('bearer '.length);

In the exercise I was getting the token but getting a failure when accessing the protected resource. e.g. checking the token in the client.js I could see I got B7agg1tSi7TpDyZiz9SgXhE2cRheu5i3 but the log for protectedResource had

Incoming token: 7agg1tSi7TpDyZiz9SgXhE2cRheu5i3
No matching token was found.

I'm new to node and not sure of the details of this slice function but when i removed the space i.e. changed to

inToken = auth.slice('bearer'.length);

it worked for me.

ch-12-ex-1 authorizationServer.js line 319 bug

if (__.contains(['client_secret_basic', 'client_secret_post']), reg.token_endpoint_auth_method) {

has the ")" position wrong, also the "client_secret_basic" in the example sometimes been mentioned as "secret_basic"

Issues on Node v20.9.0

Hi,

I've run into some issues while executing projects using Node version 20.9.0 - I allowed myself to create pull requests with fixes:
#55
#56

Best Regards,
Tomasz Mróz

Use `Buffer.from` instead of `new Buffer`

On new Node.js versions new Buffer() is deprecated Buffer.from seems like a better option for the cases that new Buffer was used in this book. I get the following error in authorizationServer.js and client.js

(node:15865) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

I used Buffer.from in both places and it seems to work just fine.

Missing "How to Install and Run the Project" section

Hi,

I've noticed that there's no "How to Install and Run the Project" section in README.md for readers that might not be proficient with JavaScript or Node environment. I've added such section, but since english is not my native language you probably might want to proofread it first. You can look it up here:
#57

Best Regards,
Tomasz Mróz

4-1: user is missing in approve form

In example 4-1 you can not recieve a token, because there is no username passed to the autorization server.

Just as a proof of concept:
It works if you just add a hard coded user name to the approve.html:

<input type="hidden" name="user" value="bob">

Best
Fabian

Additional implementations of examples

Hello and thank you so much for your very helpful book and useful examples!

I'm trying to learn about OAuth to use in a split-stack Ruby on Rails/React client application (i.e., front and back end deployed separately). In order to further my learning, I'm re-implementing your exercises in Rails and React. (Auth servers and protected resources are Rails monoliths and clients have a separate front and back end.)

I was going to push my work to a private repo so as to avoid stepping on your toes or creating copyright issues, but it occurred to me that maybe you/your readers would find it valuable to have these examples available publicly, especially since having a fully separate front and back end for the client application is a really common pattern that does introduce additional complexity.

Maybe you don't care but I just wanted to check if you/your publisher would prefer this stuff be private or if your readers might find it valuable.

"nosql": "^3.0.3" has a bug

To anybody going through the exercises after node v10.0.0,

nosql v3.0.3, used in the code exercises, has a bug in FileReader.prototype.open in index.js line 2388. The callback in fs signature is no longer optional since v7.0.0 and throws an error since node v10.0.0
However, newer versions of nosql, have a different API than the one used in the exercises code. A quick fix, just to follow the exercises: in the node_modules/nosql/index.js, at line 2388, change
fs.close(fd); to
fs.close(fd, err=>{console.log(err)});

Cheers

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.