{"id":29748548,"url":"https://github.com/webexsamples/webex-device-oauth-sample","last_synced_at":"2026-02-16T07:03:10.472Z","repository":{"id":280049253,"uuid":"870336946","full_name":"WebexSamples/webex-device-oauth-sample","owner":"WebexSamples","description":"A Python script designed to authenticate users via OAuth with the Webex APIs, specifically using the device authorization grant flow","archived":false,"fork":false,"pushed_at":"2025-07-18T20:20:52.000Z","size":882,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-26T14:48:48.894Z","etag":null,"topics":["devices","oauth2","python","samples"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WebexSamples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-09T21:19:11.000Z","updated_at":"2025-07-18T20:20:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"dddca414-4698-4447-9c4e-dbf9daa96b8b","html_url":"https://github.com/WebexSamples/webex-device-oauth-sample","commit_stats":null,"previous_names":["webexsamples/webex-device-oauth-sample"],"tags_count":0,"template":false,"template_full_name":"WebexSamples/Webex-Samples-Template","purl":"pkg:github/WebexSamples/webex-device-oauth-sample","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebexSamples%2Fwebex-device-oauth-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebexSamples%2Fwebex-device-oauth-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebexSamples%2Fwebex-device-oauth-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebexSamples%2Fwebex-device-oauth-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebexSamples","download_url":"https://codeload.github.com/WebexSamples/webex-device-oauth-sample/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebexSamples%2Fwebex-device-oauth-sample/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29502929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T05:57:17.024Z","status":"ssl_error","status_checked_at":"2026-02-16T05:56:49.929Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devices","oauth2","python","samples"],"created_at":"2025-07-26T10:38:59.609Z","updated_at":"2026-02-16T07:03:10.467Z","avatar_url":"https://github.com/WebexSamples.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Webex Device Authentication Grant Sample\n\nA comprehensive Flask application demonstrating the OAuth 2.0 Device Authorization Grant flow with Webex APIs. This sample showcases secure authentication for devices without keyboards or browsers, including QR code generation, token polling, and user profile retrieval.\n\n## 🎯 Features\n\nThis sample shows how to implement the OAuth 2.0 Device Authorization Grant flow with Webex APIs:\n\n* **Device Authorization Grant** - OAuth flow for input-constrained devices\n* **QR Code Generation** - Visual authentication for mobile devices\n* **Token Polling** - Secure background token retrieval\n* **Automatic Token Refresh** - Handle expired tokens seamlessly\n* **User Profile Retrieval** - Fetch authenticated user information\n* **Real-time Updates** - jQuery-powered status polling\n* **Secure Session Management** - Safe credential storage\n\n## 📚 Prerequisites\n\n### Software Requirements\n\n- **Python 3.6 or higher**\n- **Flask** web framework\n- **Requests** library for HTTP operations\n- **QRCode** library with PIL support\n\n### Webex Developer Account\n\n- **[Webex Developer Account](https://developer.webex.com/)** - Sign up for free\n- **Webex Integration** with device authorization capabilities\n\n## 🚀 Quick Start\n\n### Install Python Dependencies\n\nInstall the required Python modules using pip:\n\n```bash\npip install flask\npip install requests\npip install qrcode[pil]\n```\n\n**Module Details:**\n- **Flask**: Web framework for Python applications\n- **Requests**: Simplified HTTP library for API calls  \n- **QRCode[PIL]**: QR code generation with image support (includes Pillow)\n\n### Create Webex Integration\n\n1. **Navigate** to [Webex Developer Portal](https://developer.webex.com)\n2. **Log in** with your Webex account credentials\n3. **Select** \"Start building apps\" on the landing page\n4. **Choose** \"Create an Integration\" in the Integrations card\n5. **Configure** your integration:\n\n   | Field | Value |\n   |-------|-------|\n   | **Mobile SDK** | No |\n   | **Integration Name** | Your app name (alphanumeric) |\n   | **Icon** | Choose from default icons |\n   | **Description** | e.g., \"OAuth testing integration\" |\n   | **Redirect URIs** | Use the helper service URLs below |\n   | **Scopes** | `spark:all` |\n\n   **Required Redirect URIs:**\n   ```\n   https://oauth-helper-a.wbx2.com/helperservice/v1/actions/device/callback\n   https://oauth-helper-k.wbx2.com/helperservice/v1/actions/device/callback\n   https://oauth-helper-r.wbx2.com/helperservice/v1/actions/device/callback\n   ```\n\n6. **Save** your integration and securely store the **Client ID** and **Client Secret**\n\n### Setup and Run\n\n1. **Update environment variables** in the `.env` file:\n   ```env\n   CLIENT_ID=your_client_id_here\n   CLIENT_SECRET=your_client_secret_here\n   ```\n\n2. **Start the application**:\n   ```bash\n   python oauth.py\n   ```\n\n3. **Access the application** at the generated URL:\n   ```\n   Running on http://10.26.164.77:10060\n   ```\n\n4. **Authenticate** by scanning the QR code or entering the URL and code manually\n\n5. **View profile** information after successful authentication\n\n## 📁 Project Structure\n\n```\nwebex-device-oauth-sample/\n├── oauth.py                 # Main Flask application\n├── .env                     # Environment variables (not tracked)\n├── static/css/             # CSS styling files\n├── templates/              # HTML templates\n│   ├── index.html          # Landing page\n│   ├── sign-in.html        # Authentication page with QR code\n│   ├── granted.html        # Post-authentication page\n│   ├── whoami.html         # User profile display\n│   └── temp.html           # Base template\n├── package.json            # Development tools configuration\n└── README.md               # This file\n```\n\n## 🔧 Functionality Overview\n\n### OAuth 2.0 Device Authorization Grant Flow\n\n| Step | Description | Implementation |\n|------|-------------|----------------|\n| **1. Device Authorization** | Request device and user codes | `/sign-in` endpoint |\n| **2. User Authentication** | User authorizes via QR code or URL | External Webex authorization |\n| **3. Token Polling** | Background polling for access token | `poll_for_access_token()` |\n| **4. Token Retrieval** | Receive access and refresh tokens | Background thread processing |\n| **5. API Access** | Use tokens for authenticated API calls | `/whoami` endpoint |\n\n### Key Components\n\n#### Device Authorization Request\n```python\ndef sign_in():\n    scopes = \"meeting:recordings_read spark:all spark:kms\"\n    params = {'client_id': clientID, 'scope': scopes}\n    device_auth_url = \"https://webexapis.com/v1/device/authorize\"\n    device_auth_request = requests.post(url=device_auth_url, data=params)\n```\n\n#### QR Code Generation\n```python\ndef qr_cde_generation(url):\n    img = qrcode.make(url)\n    img.save('./static/qr_code.png')\n```\n\n#### Token Polling\n```python\ndef poll_for_access_token(device_code, poll_interval, secure_prefix):\n    token_url = \"https://webexapis.com/v1/device/token\"\n    while True:\n        time.sleep(poll_interval)\n        token_request = requests.post(url=token_url, data=body, headers=headers)\n        if token_request.status_code == 200:\n            # Store tokens and mark as ready\n            break\n```\n\n## 🔐 Authentication Flow\n\n### Step-by-Step Process\n\n1. **User Clicks Sign-In**: Initiates the device authorization flow\n2. **Device Authorization**: App requests device and user codes from Webex\n3. **QR Code Display**: Visual representation of the verification URL\n4. **User Authentication**: User scans QR code or visits URL to authorize\n5. **Token Polling**: App polls Webex for authorization completion\n6. **Token Storage**: Access and refresh tokens stored securely\n7. **Profile Access**: User can view their Webex profile information\n\n### Security Features\n\n- **Secure Session Management**: Random alphanumeric session prefixes\n- **Base64 Credential Encoding**: Client credentials properly encoded\n- **Automatic Token Refresh**: Handles expired tokens transparently\n- **Thread-Safe Polling**: Background token retrieval without blocking UI\n\n## 📡 API Integration\n\n### Core Endpoints\n\n#### Device Authorization\n```python\nPOST https://webexapis.com/v1/device/authorize\nContent-Type: application/x-www-form-urlencoded\n\nclient_id=YOUR_CLIENT_ID\u0026scope=spark:all\n```\n\n#### Token Exchange\n```python\nPOST https://webexapis.com/v1/device/token\nAuthorization: Basic {base64_encoded_credentials}\n\nclient_id=YOUR_CLIENT_ID\u0026device_code=DEVICE_CODE\u0026grant_type=urn:ietf:params:oauth:grant-type:device_code\n```\n\n#### User Profile\n```python\nGET https://webexapis.com/v1/people/me?callingData=true\nAuthorization: Bearer ACCESS_TOKEN\n```\n\n### Error Handling\n\nThe application includes comprehensive error handling:\n\n```python\ndef poll_for_access_token(device_code, poll_interval, secure_prefix):\n    while True:\n        token_request = requests.post(url=token_url, data=body, headers=headers)\n        if token_request.status_code == 200:\n            # Success - store tokens\n            break\n        else:\n            # Handle errors like 'slow_down', 'expired_token'\n            print(\"Response Code:\", token_request.status_code,\n                  token_request.json()['errors'][0]['description'])\n```\n\n## 🎨 User Interface\n\n### Frontend Technologies\n\n- **Flask Templates** with Jinja2 templating\n- **jQuery** for asynchronous token status checking\n- **CSS Styling** for professional appearance\n- **QR Code Display** for mobile-friendly authentication\n\n### Real-time Token Polling\n\nThe sign-in page uses jQuery to poll for token readiness:\n\n```javascript\nfunction checkAccessToken() {\n    $.ajax({\n        url: '/access_token_ready/{{ secure_prefix }}',\n        type: 'GET',\n        success: function (response) {\n            if (response.token_ready) {\n                window.location.href = '/granted/{{ secure_prefix }}';\n            } else {\n                setTimeout(checkAccessToken, 2000); // Poll every 2 seconds\n            }\n        }\n    });\n}\n```\n\n### User Experience Flow\n\n1. **Landing Page**: Simple interface with \"Sign-In\" button\n2. **Authentication Page**: QR code and manual entry options\n3. **Waiting State**: Automatic polling with user feedback\n4. **Success Page**: Confirmation and profile access\n5. **Profile Display**: Formatted JSON user information\n\n## 🔧 Configuration\n\n### Environment Variables\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `CLIENT_ID` | Webex Integration Client ID | `C1234567890abcdef...` |\n| `CLIENT_SECRET` | Webex Integration Client Secret | `secret123...` |\n\n### Application Settings\n\n```python\n# Flask configuration\napp.secret_key = os.urandom(16)  # Secure session key\napp.run(debug=True, host='0.0.0.0', port=10060)  # Development settings\n```\n\n### Scope Configuration\n\n```python\n# OAuth scopes requested\nscopes = \"meeting:recordings_read spark:all spark:kms\"\n```\n\n## 🌐 Production Considerations\n\n### Security Best Practices\n\n1. **Environment Variables**: Never hardcode credentials\n   ```python\n   clientID = os.getenv('CLIENT_ID')\n   clientSecret = os.getenv('CLIENT_SECRET')\n   ```\n\n2. **HTTPS**: Use HTTPS in production\n3. **Session Security**: Implement proper session management\n4. **Token Storage**: Use secure storage for production tokens\n\n### Deployment Recommendations\n\n```python\n# Production configuration\nif __name__ == \"__main__\":\n    port = int(os.environ.get('PORT', 10060))\n    app.run(host='0.0.0.0', port=port, debug=False)\n```\n\n### Monitoring and Logging\n\n```python\nimport logging\n\n# Configure logging for production\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\ndef poll_for_access_token(device_code, poll_interval, secure_prefix):\n    logger.info(f\"Starting token polling for session {secure_prefix}\")\n    # ... polling logic\n```\n\n## 🔧 Development\n\n### Local Development Setup\n\n1. **Virtual Environment**:\n   ```bash\n   python -m venv venv\n   source venv/bin/activate  # On Windows: venv\\Scripts\\activate\n   pip install -r requirements.txt\n   ```\n\n2. **Debug Mode**:\n   ```python\n   app.run(debug=True, host='0.0.0.0', port=10060)\n   ```\n\n### Adding Features\n\nExample: Adding token expiration checking:\n\n```python\nimport jwt\nfrom datetime import datetime\n\ndef is_token_expired(access_token):\n    try:\n        payload = jwt.decode(access_token, options={\"verify_signature\": False})\n        exp_timestamp = payload.get('exp')\n        return datetime.now().timestamp() \u003e exp_timestamp\n    except Exception:\n        return True\n```\n\n### Testing the Flow\n\n1. **Start the application**\n2. **Navigate to the landing page**\n3. **Click \"Sign-In\"** to initiate flow\n4. **Scan QR code** or enter URL manually\n5. **Authorize** in Webex\n6. **View profile** information\n\n## 🔗 Related Resources\n\n- [Webex Developer Portal](https://developer.webex.com/)\n- [OAuth 2.0 Device Authorization Grant](https://tools.ietf.org/html/rfc8628)\n- [Webex API Documentation](https://developer.webex.com/docs/api/v1/)\n- [Flask Documentation](https://flask.palletsprojects.com/)\n- [QRCode Library Documentation](https://pypi.org/project/qrcode/)\n\n## 🤝 Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Test thoroughly with Webex integrations\n5. Submit a pull request\n\n## 📄 License\n\nThis project is licensed under the **Cisco Sample Code License**.\n\n### License Summary\n\n- ✅ **Permitted**: Copy, modify, and redistribute for use with Cisco products\n- ❌ **Prohibited**: Use independent of Cisco products or to compete with Cisco\n- ℹ️ **Warranty**: Provided \"as is\" without warranty\n- ℹ️ **Support**: Not supported by Cisco TAC\n\nSee the [LICENSE](LICENSE) file for full license terms.\n\n## 🆘 Support\n\n- Create an issue in this repository\n- Visit [Webex Developer Support](https://developer.webex.com/support)\n- Join the [Webex Developer Community](https://developer.webex.com/community)\n\n---\n\n**Ready to implement device authentication with Webex!** 🚀📱\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebexsamples%2Fwebex-device-oauth-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebexsamples%2Fwebex-device-oauth-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebexsamples%2Fwebex-device-oauth-sample/lists"}