|
| 1 | +# OAuth 2.0 Device Code Flow with Microsoft Azure AD |
| 2 | + |
| 3 | +A Node.js/Express demonstration of the **OAuth 2.0 Device Authorization Grant** (Device Code Flow) using Microsoft Azure Active Directory. This project implements the complete flow for authenticating users on input-constrained devices (smart TVs, IoT devices, CLI tools) and calling the Microsoft Graph API. |
| 4 | + |
| 5 | +## 📋 Overview |
| 6 | + |
| 7 | +The Device Code Flow is an OAuth 2.0 extension that enables devices with limited input capabilities or without a web browser to obtain user authorization. Instead of entering credentials on the device itself, users authenticate on a separate device (like a smartphone or computer) by visiting a URL and entering a code. |
| 8 | + |
| 9 | +This demo walks through the complete 4-step flow: |
| 10 | +1. **Get Device Code** — Request a device code and user code from Azure AD |
| 11 | +2. **User Authentication** — User visits the verification URL and enters the code |
| 12 | +3. **Retrieve Access Token** — Poll for the access token once the user has authenticated |
| 13 | +4. **Call Microsoft Graph API** — Use the access token to call the beta `/me` endpoint |
| 14 | + |
| 15 | +## 🎯 Prerequisites |
| 16 | + |
| 17 | +Before running this project, ensure you have: |
| 18 | + |
| 19 | +- **Node.js** (v14 or higher) |
| 20 | +- **An Azure AD tenant** with administrative access |
| 21 | +- **A registered Azure AD application** with: |
| 22 | + - **Application (client) ID** |
| 23 | + - **Directory (tenant) ID** |
| 24 | + - **API Permissions**: `User.Read` (Microsoft Graph) |
| 25 | + - **Public client flows enabled** (Authentication → Advanced settings → Allow public client flows: Yes) |
| 26 | + |
| 27 | +### Azure AD Application Setup |
| 28 | + |
| 29 | +1. Go to [Azure Portal](https://portal.azure.com) → Azure Active Directory → App registrations |
| 30 | +2. Click **New registration** |
| 31 | +3. Enter a name for your application |
| 32 | +4. Under **Supported account types**, choose the appropriate option (single or multi-tenant) |
| 33 | +5. Click **Register** |
| 34 | +6. Note down the **Application (client) ID** and **Directory (tenant) ID** |
| 35 | +7. Navigate to **API permissions** → Add **Microsoft Graph** → Delegated permissions → Add `User.Read` |
| 36 | +8. Navigate to **Authentication** → Advanced settings → Enable **Allow public client flows** |
| 37 | + |
| 38 | +## 🚀 Installation & Setup |
| 39 | + |
| 40 | +1. **Clone the repository:** |
| 41 | + |
| 42 | +```bash |
| 43 | +git clone https://github.com/0GiS0/oauth2-device-code-flow.git |
| 44 | +cd oauth2-device-code-flow |
| 45 | +``` |
| 46 | + |
| 47 | +2. **Install dependencies:** |
| 48 | + |
| 49 | +```bash |
| 50 | +npm install |
| 51 | +``` |
| 52 | + |
| 53 | +3. **Configure environment variables:** |
| 54 | + |
| 55 | +Copy the `.env.sample` file to `.env`: |
| 56 | + |
| 57 | +```bash |
| 58 | +cp .env.sample .env |
| 59 | +``` |
| 60 | + |
| 61 | +Edit the `.env` file and add your Azure AD credentials: |
| 62 | + |
| 63 | +``` |
| 64 | +TENANT_ID="your-tenant-id" |
| 65 | +CLIENT_ID="your-client-id" |
| 66 | +``` |
| 67 | + |
| 68 | +## 🎮 Usage |
| 69 | + |
| 70 | +Start the server: |
| 71 | + |
| 72 | +```bash |
| 73 | +npm start |
| 74 | +``` |
| 75 | + |
| 76 | +The application will start on `http://localhost:8000`. |
| 77 | + |
| 78 | +### Device Code Flow Steps |
| 79 | + |
| 80 | +1. **Navigate to** `http://localhost:8000` |
| 81 | + |
| 82 | +2. **Step 1: Get the Device Code** |
| 83 | + - Click "Get the device code" button |
| 84 | + - The app requests a device code from Azure AD |
| 85 | + - You'll see a user code and verification URL |
| 86 | + |
| 87 | +3. **Step 2: User Authentication** |
| 88 | + - Open the verification URL (e.g., `https://microsoft.com/devicelogin`) in a browser |
| 89 | + - Enter the user code displayed in the app |
| 90 | + - Sign in with your Microsoft account |
| 91 | + - Grant consent to the application |
| 92 | + |
| 93 | +4. **Step 3: Retrieve Access Token** |
| 94 | + - The app polls Azure AD for the access token |
| 95 | + - Once authentication is complete, the access token is retrieved |
| 96 | + |
| 97 | +5. **Step 4: Call Microsoft Graph API** |
| 98 | + - The app uses the access token to call the Microsoft Graph beta `/me` endpoint |
| 99 | + - Your user profile information is displayed |
| 100 | + |
| 101 | +## 📁 Project Structure |
| 102 | + |
| 103 | +``` |
| 104 | +oauth2-device-code-flow/ |
| 105 | +├── server.js # Main Express server and OAuth 2.0 flow implementation |
| 106 | +├── package.json # Project dependencies and scripts |
| 107 | +├── .env.sample # Template for environment variables |
| 108 | +├── .gitignore # Git ignore rules |
| 109 | +├── views/ # EJS templates |
| 110 | +│ ├── index.ejs # Landing page with 4-step stepper |
| 111 | +│ ├── device-code.ejs # Device code display and polling logic |
| 112 | +│ ├── access-token.ejs # Access token display |
| 113 | +│ ├── calling-ms-graph.ejs # Microsoft Graph API response |
| 114 | +│ └── partials/ # Reusable EJS components |
| 115 | +└── public/ # Static assets (CSS, JS) |
| 116 | +``` |
| 117 | + |
| 118 | +### Key Files |
| 119 | + |
| 120 | +- **`server.js`** — Contains all Express routes and OAuth 2.0 Device Code Flow logic: |
| 121 | + - `GET /get/the/code` — Initiates the device code request |
| 122 | + - `POST /checking` — Polls Azure AD for token |
| 123 | + - `GET /access/token` — Displays the retrieved access token |
| 124 | + - `POST /call/ms/graph` — Calls Microsoft Graph API |
| 125 | + |
| 126 | +- **`.env.sample`** — Template for required environment variables |
| 127 | + |
| 128 | +- **`views/index.ejs`** — Landing page with visual stepper showing the 4-step flow |
| 129 | + |
| 130 | +## 🛠️ Technologies Used |
| 131 | + |
| 132 | +- **[Express](https://expressjs.com/)** — Web framework for Node.js |
| 133 | +- **[EJS](https://ejs.co/)** — Embedded JavaScript templating |
| 134 | +- **[node-fetch](https://github.com/node-fetch/node-fetch)** — HTTP client for making API requests |
| 135 | +- **[bunyan](https://github.com/trentm/node-bunyan)** — JSON logging library |
| 136 | +- **[dotenv](https://github.com/motdotla/dotenv)** — Environment variable management |
| 137 | +- **[body-parser](https://github.com/expressjs/body-parser)** — Request body parsing middleware |
| 138 | +- **[nodemon](https://nodemon.io/)** — Development tool for auto-restarting the server |
| 139 | + |
| 140 | +## 📚 Documentation & References |
| 141 | + |
| 142 | +- [OAuth 2.0 Device Authorization Grant — RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628) |
| 143 | +- [Microsoft Identity Platform — Device Code Flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-device-code) |
| 144 | +- [Microsoft Graph API — Get User](https://learn.microsoft.com/en-us/graph/api/user-get) |
| 145 | +- [Azure AD App Registration Guide](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app) |
| 146 | + |
| 147 | +## 🔒 Security Considerations |
| 148 | + |
| 149 | +- **Never commit your `.env` file** — It contains sensitive credentials |
| 150 | +- **Access tokens are displayed for demo purposes** — In production, never expose tokens to the client-side |
| 151 | +- **Use HTTPS in production** — Always serve your application over HTTPS |
| 152 | +- **Implement token refresh** — Access tokens expire; implement refresh token logic for production use |
| 153 | +- **Limit token scope** — Only request the minimum necessary permissions |
| 154 | + |
| 155 | +## 📝 License |
| 156 | + |
| 157 | +This project is licensed under the **ISC License**. |
| 158 | + |
| 159 | +## 🤝 Contributing |
| 160 | + |
| 161 | +Contributions are welcome! Please feel free to submit a Pull Request. |
| 162 | + |
| 163 | +## 👤 Author |
| 164 | + |
| 165 | +**@0GiS0** |
| 166 | + |
| 167 | +--- |
| 168 | + |
| 169 | +⭐ If you found this demo helpful, please consider giving it a star! |
0 commit comments