I hereby claim:
- I am anishsujanani on github.
- I am anishsujanani (https://keybase.io/anishsujanani) on keybase.
- I have a public key ASCvBqQC8nQ2poTaZmx_K8ui6Fwx5-jJ3DZLpALNfabGBQo
To claim this, I am signing this object:
I hereby claim:
To claim this, I am signing this object:
| app.post('/consent', (req, res) => { | |
| var token = null; | |
| // implement a new scope here | |
| // that when requested, sends back all details about the user | |
| // eg. the roles that the user has across applications and any custom attributes | |
| // this may be used across internal applications and services and even for SSO | |
| if (req.body.selected_scope == 'getallrolesandperms') { | |
| token = { |
| // client applications would POST here | |
| // with a code that this server sent out earlier after resource-owner authentication | |
| app.post('/token', (req, res) => { | |
| // make sure that the code is still alive and can be exchanged | |
| if (code_token_cache[req.body.code]) { | |
| console.log('sending back token for code', code_token_cache[req.body.code]); | |
| // perform client app authentication here, they need to send over the 'client_secret' | |
| if (registered_clients[req.body.client_id].client_secret != req.body.client_secret) { | |
| res.send('Client failed authentication'); |
| // this endpoint recieves a code and a state | |
| // checks if state matches the state_cache ie. has a request gone out and is a code awaited? | |
| // if so, get the code from the query_string, exchange that once again with the auth server for an actual token | |
| // why is this done? - Code for Token exchange is done on a secure back-channel | |
| app.get('/oauth_callback', (req, res) => { | |
| // make sure that a request has gone out, and that we are actually awaiting a code | |
| // and unsolicited responses are not being serviced | |
| if (!state_cache.includes(req.query.state)) { | |
| res.send('State has changed, either the flow took too long or CSRF'); | |
| } |
| // perform user authentication here, store a session - req.session.username | |
| app.post('/consent', (req, res) => { | |
| // this token below later is treated as the payload of a JWT | |
| var token = {authorized: true, username: 'username_here_from_auth_server_session', scope: req.body.selected_scope}; | |
| var code = crypto.randomBytes(5).toString('hex'); | |
| // typically, also add functionality to time the validity of this token | |
| // code-token mapping is implemented to prevent CSRF as well as time-out auth flows if they take too long | |
| // to prevent vectors such as replay attacks | |
| code_token_cache[code] = token; |
| <html> | |
| <body> | |
| <h1> Auth-Server Page</h1> | |
| <h3><%= client_uri %></h3> has requested for scopes: <h3><%= selected_scope %></h3> | |
| <br> | |
| Normally I would ask for username/password, but for simiplicity, just click below: | |
| <br> | |
| Once you consent, I will redirect you to <h3><%= client_redirect_uri %></h3> | |
| <form action="/consent" method=POST> | |
| <input type="hidden" name="selected_scope", value="<%= selected_scope %>"/> |
| // given a set of client details that have hit the /auth endpoint, | |
| // check if they are valid and if a code should be issued | |
| // this implementation checks for existance of client_id, referer, redirect_uri, | |
| // requires response_type == 'code', requries state parameter | |
| const validate_client = (client_details) => { | |
| var known_client = registered_clients[client_details.client_id]; | |
| if(known_client == null) | |
| return false; | |
| if (client_details.referer == known_client.referer) { |
| const express = require('express'); | |
| const bodyparser = require('body-parser'); | |
| const path = require('path'); | |
| const crypto = require('crypto'); | |
| const jwt = require('jsonwebtoken'); | |
| const fs = require('fs'); | |
| // for each client, we need to store the origin, client_id, client_secret, client_type | |
| const registered_clients = { | |
| client_1 : { |
| app.post('/authme', (req, res) => { | |
| var state = crypto.randomBytes(10).toString('hex'); | |
| params = `?response_type=code&client_id=${client_id}&scope=${req.body.selected_scope}&state=${state}&redirect_uri=${redirect_uri}`; | |
| state_cache.push(state); | |
| res.redirect( auth_server_authorize_endpoint + params ); | |
| }); |
| <html> | |
| <body> | |
| <form action="/authme", method="POST"> | |
| Scope: resorce1: read<input type="radio" name="selected_scope" value="resource1_read"> | |
| <br> | |
| Scope: resource1: read, resource1: write<input type="radio" name="selected_scope" value="resource1_read resource1_write"> | |
| <button type="submit" value="Authenticate Me">Authenticate Me</button> | |
| </form> | |
| </body> |