-
Notifications
You must be signed in to change notification settings - Fork 93
Add a GitHub OAuth sample for Socket.IO #624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2243676
fa814e5
c179f2e
a1eb204
11f790c
d816eb1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,44 @@ | ||||||
| # Create a chat app with Web PubSub for Socket.IO And GitHub OAuth | ||||||
|
|
||||||
| ## Prerequisites | ||||||
|
|
||||||
| 1. [Node.js](https://nodejs.org) | ||||||
| 2. Create an Web PubSub For Socket.IO resource | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| ## Setup | ||||||
|
|
||||||
| ```bash | ||||||
| npm install | ||||||
| ``` | ||||||
|
|
||||||
| ## Get Github ClientID | ||||||
|
|
||||||
| 1. Go to https://www.github.com, open your profile -> Settings -> Developer settings | ||||||
| 2. Go to OAuth Apps, click "New OAuth App" | ||||||
| 3. Fill in application name, homepage URL (can be anything you like), and set Authorization callback URL to `http://localhost:3000/auth/github/callback` (which matches the callback API you exposed in the server) | ||||||
| 4. After the application is registered, copy the **Client ID** and click "Generate a new client secret" to generate a new **client secret** | ||||||
|
|
||||||
| ## Start the app | ||||||
| Copy **Connection String** from **Keys** tab of the Web PubSub For Socket.IO resource, and replace the `<connection-string>` below with the value of your **Connection String**. | ||||||
|
|
||||||
| Linux: | ||||||
|
|
||||||
| ```bash | ||||||
| export WebPubSubConnectionString="<connection_string>" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how about using |
||||||
| export GitHubClientId="<client-id>" | ||||||
| export GitHubClientSecret="<client-secret>" | ||||||
| npm run start | ||||||
| ``` | ||||||
|
|
||||||
| Windows: | ||||||
|
|
||||||
| ```cmd | ||||||
| SET WebPubSubConnectionString=<connection_string> | ||||||
| SET GitHubClientId=<client-id> | ||||||
| SET GitHubClientSecret=<client-secret> | ||||||
| npm run start | ||||||
| ``` | ||||||
|
|
||||||
| ## Start the chat | ||||||
|
|
||||||
| Open http://localhost:3000, after authenticated by GibHub, you could start your chat with others with your GitHub username. | ||||||
| Original file line number | Diff line number | Diff line change | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,143 @@ | |||||||||||||||||||||||||||||
| const express = require('express'); | |||||||||||||||||||||||||||||
| const session = require("express-session"); | |||||||||||||||||||||||||||||
| const bodyParser = require("body-parser"); | |||||||||||||||||||||||||||||
| const passport = require("passport"); | |||||||||||||||||||||||||||||
| const GitHubStrategy = require('passport-github2').Strategy; | |||||||||||||||||||||||||||||
| const azure = require("@azure/web-pubsub-socket.io"); | |||||||||||||||||||||||||||||
| const wrap = middleware => (socket, next) => middleware(socket.request, {}, next); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| const app = express(); | |||||||||||||||||||||||||||||
| const server = require("http").createServer(app); | |||||||||||||||||||||||||||||
| const store = new session.MemoryStore(); | |||||||||||||||||||||||||||||
| const sessionMiddleware = session({ store: store, secret: "changeit", resave: false, saveUninitialized: false }); | |||||||||||||||||||||||||||||
Check warningCode scanning / CodeQL Clear text transmission of sensitive cookie Medium
Sensitive cookie sent without enforcing SSL encryption.
Copilot AutofixAI 7 months ago To correct the issue, set the However, for development environments running over plain HTTP, using Therefore, update the options passed to No additional imports or methods are required.
Suggested changeset
1
sdk/webpubsub-socketio-extension/examples/chat-with-auth-github/index.js
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
|||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| app.use(sessionMiddleware); | |||||||||||||||||||||||||||||
| app.use(bodyParser.urlencoded({ extended: false })); | |||||||||||||||||||||||||||||
| app.use(passport.initialize()); | |||||||||||||||||||||||||||||
| app.use(passport.session()); | |||||||||||||||||||||||||||||
| app.get('/auth/github', passport.authenticate('github', { scope: ['user:email'] })); | |||||||||||||||||||||||||||||
| app.get('/auth/github/callback', passport.authenticate('github', { successRedirect: '/' })); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| var users = []; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| passport.use( | |||||||||||||||||||||||||||||
| new GitHubStrategy({ | |||||||||||||||||||||||||||||
| clientID: process.env.GitHubClientId, | |||||||||||||||||||||||||||||
| clientSecret: process.env.GitHubClientSecret | |||||||||||||||||||||||||||||
| }, | |||||||||||||||||||||||||||||
| (accessToken, refreshToken, profile, done) => { | |||||||||||||||||||||||||||||
| console.log(`${profile.username}(${profile.displayName}) authenticated`); | |||||||||||||||||||||||||||||
| users[profile.id] = profile; | |||||||||||||||||||||||||||||
| return done(null, profile); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
| )); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| passport.serializeUser((user, done) => { | |||||||||||||||||||||||||||||
| console.log(`serializeUser ${user.id}`); | |||||||||||||||||||||||||||||
| done(null, user.id); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| passport.deserializeUser((id, done) => { | |||||||||||||||||||||||||||||
| console.log(`deserializeUser ${id}`); | |||||||||||||||||||||||||||||
| if (users[id]) return done(null, users[id]); | |||||||||||||||||||||||||||||
| return done(`invalid user id: ${id}`); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| app.post("/login", passport.authenticate("local", { | |||||||||||||||||||||||||||||
| successRedirect: "/", | |||||||||||||||||||||||||||||
| failureRedirect: "/", | |||||||||||||||||||||||||||||
| }) | |||||||||||||||||||||||||||||
| ); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| async function main() { | |||||||||||||||||||||||||||||
| const wpsOptions = { | |||||||||||||||||||||||||||||
| hub: "eio_hub", | |||||||||||||||||||||||||||||
| connectionString: process.argv[2] || process.env.WebPubSubConnectionString, | |||||||||||||||||||||||||||||
| }; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| const io = require('socket.io')(server); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| await azure.useAzureSocketIO(io, wpsOptions); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| app.get("/negotiate", azure.negotiate(io, azure.usePassport())); | |||||||||||||||||||||||||||||
| io.use(wrap(azure.restorePassport())); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| io.use(wrap(passport.initialize())); | |||||||||||||||||||||||||||||
| io.use(wrap(passport.session())); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // Now `socket.request.user` is available. While `req.request.session` is not. | |||||||||||||||||||||||||||||
| io.use((socket, next) => { | |||||||||||||||||||||||||||||
| if (socket.request.user) { | |||||||||||||||||||||||||||||
| next(); | |||||||||||||||||||||||||||||
| } else { | |||||||||||||||||||||||||||||
| next(new Error('unauthorized')) | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| io.on('connect', (socket) => { | |||||||||||||||||||||||||||||
| console.log(`new connection ${socket.id}`); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| console.log(`socket.request.user.id = ${socket.request.user.id}`); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| socket.on('whoami', (cb) => { | |||||||||||||||||||||||||||||
| console.log(`${socket.request.user.username}`); | |||||||||||||||||||||||||||||
| cb(`${socket.request.user.username}`); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| let numUsers = 0; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| io.on('connection', socket => { | |||||||||||||||||||||||||||||
| let addedUser = false; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // when the client emits 'new message', this listens and executes | |||||||||||||||||||||||||||||
| socket.on('new message', (data) => { | |||||||||||||||||||||||||||||
| // we tell the client to execute 'new message' | |||||||||||||||||||||||||||||
| socket.broadcast.emit('new message', { | |||||||||||||||||||||||||||||
| username: socket.username, | |||||||||||||||||||||||||||||
| message: data | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // when the client emits 'add user', this listens and executes | |||||||||||||||||||||||||||||
| socket.on('add user', (username) => { | |||||||||||||||||||||||||||||
| if (addedUser) return; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // we store the username in the socket session for this client | |||||||||||||||||||||||||||||
| socket.username = username; | |||||||||||||||||||||||||||||
| ++numUsers; | |||||||||||||||||||||||||||||
| addedUser = true; | |||||||||||||||||||||||||||||
| socket.emit('login', { | |||||||||||||||||||||||||||||
| numUsers: numUsers | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| // echo globally (all clients) that a person has connected | |||||||||||||||||||||||||||||
| socket.broadcast.emit('user joined', { | |||||||||||||||||||||||||||||
| username: socket.username, | |||||||||||||||||||||||||||||
| numUsers: numUsers | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // when the user disconnects.. perform this | |||||||||||||||||||||||||||||
| socket.on('disconnect', () => { | |||||||||||||||||||||||||||||
| if (addedUser) { | |||||||||||||||||||||||||||||
| --numUsers; | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| // echo globally that this client has left | |||||||||||||||||||||||||||||
| socket.broadcast.emit('user left', { | |||||||||||||||||||||||||||||
| username: socket.username, | |||||||||||||||||||||||||||||
| numUsers: numUsers | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| app.use(express.static('public')); | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| const port = 3000; | |||||||||||||||||||||||||||||
| server.listen(port, () => { | |||||||||||||||||||||||||||||
| console.log(`application is running at: http://localhost:${port}`); | |||||||||||||||||||||||||||||
| }); | |||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| main(); | |||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "name": "chat-with-auth-github", | ||
| "version": "1.0.0", | ||
| "description": "", | ||
| "main": "server.js", | ||
| "scripts": { | ||
| "start": "node index.js" | ||
| }, | ||
| "keywords": [], | ||
| "author": "", | ||
| "license": "ISC", | ||
| "dependencies": { | ||
| "@azure/web-pubsub-socket.io": "1.0.0-beta.6", | ||
| "express": "^4.17.1", | ||
| "express-session": "^1.17.1", | ||
| "passport": "^0.4.1", | ||
| "passport-github2": "^0.1.12" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <title>Socket.IO Chat Example</title> | ||
| <link rel="stylesheet" href="style.css"> | ||
| </head> | ||
| <body> | ||
| <ul class="pages"> | ||
| <li class="chat page"> | ||
| <div class="chatArea"> | ||
| <ul class="messages"></ul> | ||
| </div> | ||
| <input class="inputMessage" placeholder="Type here..."/> | ||
| </li> | ||
| </ul> | ||
| <!-- | ||
| <script> | ||
| var names = ["Bob", "Alice","John","Alex","Cooper","James", "Jack", "Rose", "Justin", "Julia", "White", "Black", "Green"]; | ||
| var idx = Math.floor(Math.random()*100) % names.length; | ||
| document.querySelector('.usernameInput').value = names[idx]; | ||
| </script> | ||
| --> | ||
| <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script> | ||
Check warningCode scanning / CodeQL Inclusion of functionality from an untrusted source Medium
Script loaded from content delivery network with no integrity check.
|
||
| <script src="/socket.io/socket.io.min.js" crossorigin="anonymous"></script> | ||
| <script src="./main.js"></script> | ||
| </body> | ||
| </html> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this chat app with GitHub OAuth referencing any tutorial? Do you want to mention what are the lines updated specifically for Web PubSub?