Skip to content

Commit

Permalink
Manual OAuth 2.0 (#16)
Browse files Browse the repository at this point in the history
* manual oauth wip

* restore token

* store verifier

* more wip, up to 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'

* session secret

* subscribers

* working on getting token

* get it working

* just use fetch

* Update index.js

Co-authored-by: Ammar Ansari <[email protected]>

* Update index.js

Co-authored-by: Ammar Ansari <[email protected]>

* migrate axios to fetch

* use template string

---------

Co-authored-by: Ammar Ansari <[email protected]>
  • Loading branch information
ryanwi and iAmmar7 authored Jan 11, 2024
1 parent a527ce7 commit 8dd81be
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 300 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The `reference` field (aka subscriber) will be used in the future for inbound ca



In the example application, we use `axios` to retrieve the token.
In the example application, we use `fetch` to retrieve the token.

## Instantiate the client and call the destination

Expand All @@ -53,4 +53,4 @@ const call = await client.dial({
await call.start()
```

For now, please run with debugging on to help with reporting issues.
For now, please run with debugging on to help with reporting issues.
7 changes: 6 additions & 1 deletion env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ OAUTH_CLIENT_ID=<foo>
OAUTH_SECRET=<foo>
OAUTH_TOKEN_URI=https://id.fabric.swire.io/oauth/token
OAUTH_AUTH_URI=https://id.fabric.swire.io/login/oauth/authorize
OAUTH_REDIRECT_URI=https://<foo>.ngrok-free.app/callback
OAUTH_REDIRECT_URI=https://<foo>.ngrok-free.app/callback

SESSION_SECRET=

SUBSCRIBER_REFERENCE=
SUBSCRIBER_PASSWORD=
93 changes: 63 additions & 30 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
require('dotenv').config();
const express = require('express');
const session = require('express-session');
const app = express();
const axios = require('axios');
const ClientOAuth2 = require('client-oauth2')
const base64url = require('base64url');
const crypto = require('crypto');

app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static('public'));
app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: true }));

const FIREBASE_CONFIG = JSON.stringify({
apiKey: process.env.FIREBASE_API_KEY,
Expand All @@ -28,26 +30,24 @@ const token_request = {

const host = process.env.RELAY_HOST

const oauthConfig = {
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_SECRET,
accessTokenUri: process.env.OAUTH_TOKEN_URI,
authorizationUri: process.env.OAUTH_AUTH_URI,
redirectUri: process.env.OAUTH_REDIRECT_URI
}

const oauthClient = new ClientOAuth2(oauthConfig)

async function apiRequest(endpoint, payload = {}, method = 'POST') {
var url = `https://${process.env.SIGNALWIRE_SPACE}${endpoint}`

resp = await axios.post(url, payload, {
auth: {
username: process.env.SIGNALWIRE_PROJECT_KEY,
password: process.env.SIGNALWIRE_TOKEN
}
})
return resp.data
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${Buffer.from(`${process.env.SIGNALWIRE_PROJECT_KEY}:${process.env.SIGNALWIRE_TOKEN}`).toString('base64')}`
},
body: JSON.stringify(payload)
});

if (response.ok) {
return await response.json();
} else {
console.log(await response.text());
throw new Error(`HTTP error! status: ${response.status}`);
}
}

app.get('/', async (req, res) => {
Expand All @@ -71,21 +71,54 @@ app.get('/minimal', async (req, res) => {
});

app.get('/oauth', (req, res) => {
const authorizationUri = oauthClient.code.getUri()
console.log("oauth: begin initiation");

const authEndpoint = process.env.OAUTH_AUTH_URI;
const verifier = base64url(crypto.pseudoRandomBytes(32));
req.session.verifier = verifier;
const challenge = base64url(crypto.createHash('sha256').update(verifier).digest());

const queryParams = new URLSearchParams({
response_type: 'code',
client_id: process.env.OAUTH_CLIENT_ID,
redirect_uri: process.env.OAUTH_REDIRECT_URI,
code_challenge: challenge,
code_challenge_method: 'S256'
})

res.redirect(authorizationUri)
const authorizationUri = `${authEndpoint}?${queryParams}`

res.redirect(authorizationUri);
});

app.get('/callback', async (req, res) => {
const credentials = await oauthClient.code.getToken(req.originalUrl);

res.render('index', {
host,
token: credentials.accessToken,
destination: process.env.DEFAULT_DESTINATION,
firebaseConfig: FIREBASE_CONFIG,
console.log("oauth: process callback");

const params = new URLSearchParams();
params.append('client_id', process.env.OAUTH_CLIENT_ID);
params.append('grant_type', 'authorization_code');
params.append('code', req.query.code);
params.append('redirect_uri', process.env.OAUTH_REDIRECT_URI);
params.append('code_verifier', req.session.verifier);

const response = await fetch(process.env.OAUTH_TOKEN_URI, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params
});
})

if (response.ok) {
const data = await response.json();
res.render('index', {
host,
token: data.access_token,
destination: process.env.DEFAULT_DESTINATION,
firebaseConfig: FIREBASE_CONFIG,
});
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
});

app.get('/service-worker.js', async (req, res) => {
res.set({
Expand All @@ -99,4 +132,4 @@ app.get('/service-worker.js', async (req, res) => {

app.listen(process.env.PORT || 3000, () => {
console.log("Server running on port 3000");
});
});
Loading

0 comments on commit 8dd81be

Please sign in to comment.