Skip to content

Commit 2d661f6

Browse files
Adam WolfmanAdam Wolfman
authored andcommitted
first-commit
0 parents  commit 2d661f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2344
-0
lines changed

.DS_Store

8 KB
Binary file not shown.

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
*# Python-Flask Example Appplications powered by WorkOS
2+
*
3+
Example applications demonstrating to use the [WorkOS Python SDK](_https://github.com/workos-inc/workos-python_) for SSO, Directory Sync, Admin Portal and Magic Link.
4+
5+
*## For more information, please see the following guides:
6+
*
7+
* [Single Sign-On](_https://workos.com/docs/sso/guide_)
8+
* [Directory Sync](_https://workos.com/docs/directory-sync/guide_)
9+
* [Admin Portal](_https://workos.com/docs/admin-portal/guide_)
10+
* [Magic Link](_https://workos.com/docs/magic-link/guide_)
11+
12+
* [API Reference](_https://workos.com/docs/reference_)
13+
14+
*## Need help?
15+
*
16+
If you get stuck and aren't able to resolve the issue by reading our [WorkOS Python SDK documentation](_https://docs.workos.com/sdk/python_) or [API reference](_https://workos.com/docs/reference_), you can reach out to us at [email protected] and we'll lend a hand!
6 KB
Binary file not shown.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95+
__pypackages__/
96+
97+
# Celery stuff
98+
celerybeat-schedule
99+
celerybeat.pid
100+
101+
# SageMath parsed files
102+
*.sage.py
103+
104+
# Environments
105+
.env
106+
.venv
107+
env/
108+
venv/
109+
ENV/
110+
env.bak/
111+
venv.bak/
112+
113+
# Spyder project settings
114+
.spyderproject
115+
.spyproject
116+
117+
# Rope project settings
118+
.ropeproject
119+
120+
# mkdocs documentation
121+
/site
122+
123+
# mypy
124+
.mypy_cache/
125+
.dmypy.json
126+
dmypy.json
127+
128+
# Pyre type checker
129+
.pyre/
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 WorkOS
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# python-flask-admin-portal-example
2+
An example Flask application demonstrating how to use the [WorkOS Python SDK](https://github.com/workos-inc/workos-python) so your customers can access the WorkOS Admin Portal from your application.
3+
4+
## Prerequisites
5+
- Python 3.6+
6+
7+
## Flask Project Setup
8+
9+
1. In your CLI, navigate to the directory into which you want to clone this git repo.
10+
```bash
11+
$ cd ~/Desktop/
12+
```
13+
14+
2. Clone this git repo using your preferred secure method (HTTPS or SSH).
15+
```bash
16+
# HTTPS
17+
$ git clone https://github.com/workos-inc/python-flask-admin-portal-example.git
18+
```
19+
20+
or
21+
22+
```bash
23+
# SSH
24+
$ git clone [email protected]:workos-inc/python-flask-admin-portal-example.git
25+
```
26+
27+
3. Navigate to the cloned repo.
28+
```bash
29+
$ cd python-flask-admin-portal-example
30+
```
31+
32+
4. Create and source a Python virtual environment. You should then see `(env)` at the beginning of your command-line prompt.
33+
```bash
34+
$ python3 -m venv env
35+
$ source env/bin/activate
36+
(env) $
37+
```
38+
39+
5. Install the cloned app's dependencies.
40+
```bash
41+
(env) $ pip install -r requirements.txt
42+
```
43+
44+
6. Obtain and make note of the following values. In the next step, these will be set as environment variables.
45+
- Your [WorkOS API key](https://dashboard.workos.com/api-keys)
46+
- Your `WORKOS_CLIENT_ID`, in the format `client_<random-alphanumeric-string>`, retrievable from WorkOS dashboard under "Configuration".
47+
48+
7. Ensure you're in the root directory for the example app, `python-flask-admin-portal-example/`. Create a `.env` file to securely store the environment variables. Open this file with the Nano text editor. (This file is listed in this repo's `.gitignore` file, so your sensitive information will not be checked into version control.)
49+
```bash
50+
(env) $ touch .env
51+
(env) $ nano .env
52+
```
53+
54+
8. Once the Nano text editor opens, you can directly edit the `.env` file by listing the environment variables:
55+
```bash
56+
export WORKOS_API_KEY=<value found in step 6>
57+
export WORKOS_CLIENT_ID=<value found in step 6>
58+
```
59+
60+
To exit the Nano text editor, type `CTRL + x`. When prompted to "Save modified buffer", type `Y`, then press the `Enter` or `Return` key.
61+
62+
9. Source the environment variables so they are accessible to the operating system.
63+
```bash
64+
(env) $ source .env
65+
```
66+
67+
You can ensure the environment variables were set correctly by running the following commands. The output should match the corresponding values.
68+
```bash
69+
(env) $ echo $WORKOS_API_KEY
70+
(env) $ echo $WORKOS_CLIENT_ID
71+
```
72+
73+
10. Update the Admin Portal Redirect Link in the "Configuration" page of your WorkOS Dashboard. The URL should be http://localhost:5000.
74+
75+
After an Admin Portal user creates an SSO connection using the Admin Portal, they need to be redirected to a webpage within your application (usually this webpage confirms successful creation of the connection). To configure which webpage this is, enter the webpage’s URL in the Configuration section of your WorkOS dashboard under the “Admin Portal Redirect Link” header. For production usage this URL must begin with HTTPS, but for development purposes the URL can begin with HTTP.
76+
77+
## Start the server
78+
79+
11. The final setup step is to start the server.
80+
```bash
81+
(env) $ flask run
82+
```
83+
84+
You'll know the server is running when you see no errors in the CLI, and output similar to the following is displayed:
85+
86+
```bash
87+
* Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
88+
* Environment: production
89+
WARNING: This is a development server. Do not use it in a production deployment.
90+
Use a production WSGI server instead.
91+
* Debug mode: off
92+
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
93+
```
94+
95+
Navigate to `localhost:5000` in your web browser to view the homepage of the Admin Portal example app. Enter the name of the new Organization to be created and the names of all of the Organization's associated domains.
96+
97+
- The Organization must be a new Organization that doesn't yet exist in your WorkOS dashboard
98+
- The domains should be entered as space-separated values, e.g. "domain1.com domain2.com domain3.com"
99+
100+
Then, click the buttons to either create a new SSO connection or a new Directory Sync connection.
101+
102+
Hooray!
103+
104+
## Need help?
105+
106+
If you get stuck and aren't able to resolve the issue by reading our API reference or tutorials, you can reach out to us at [email protected] and we'll lend a hand.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import os
2+
3+
from flask import (Flask, redirect, render_template, request, url_for)
4+
import workos
5+
from workos import client as workos_client
6+
from workos import portal
7+
8+
9+
# Flask Setup
10+
DEBUG = False
11+
app = Flask(__name__)
12+
13+
# WorkOS Setup
14+
workos.api_key = os.getenv('WORKOS_API_KEY')
15+
workos.project_id = os.getenv('WORKOS_CLIENT_ID')
16+
workos.base_api_url = 'http://localhost:7000/' if DEBUG else workos.base_api_url
17+
18+
@app.route('/')
19+
def index():
20+
return render_template('index.html')
21+
22+
@app.route('/provision_enterprise', methods=['POST'])
23+
def provision_enterprise():
24+
# Create global variable for org_id
25+
global org_id
26+
organization_name = request.form['org']
27+
organization_domains = request.form['domain'].split()
28+
29+
# Check if a matching domain already exists and set global org_id if there is a match
30+
orgs = workos_client.organizations.list_organizations(domains=organization_domains)
31+
if len(orgs["data"]) > 0:
32+
org_id = orgs['data'][0]['id']
33+
34+
# Otherwise create a new Organization and set the global org_id
35+
else:
36+
organization = workos_client.organizations.create_organization({
37+
'name': organization_name,
38+
'domains': organization_domains
39+
})
40+
org_id = organization['id']
41+
42+
return render_template('org_logged_in.html')
43+
44+
@app.route('/sso_admin_portal', methods=['GET', 'POST'])
45+
def sso_admin_portal():
46+
portal_link = workos_client.portal.generate_link(
47+
organization=org_id, intent='sso'
48+
)
49+
return redirect(portal_link['link'])
50+
51+
@app.route('/dsync_admin_portal', methods=['GET', 'POST'])
52+
def dsync_admin_portal():
53+
portal_link = workos_client.portal.generate_link(
54+
organization=org_id, intent='dsync'
55+
)
56+
return redirect(portal_link['link'])
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
certifi==2021.5.30
2+
charset-normalizer==2.0.6
3+
click==8.0.1
4+
Flask==2.0.1
5+
idna==3.2
6+
itsdangerous==2.0.1
7+
Jinja2==3.0.1
8+
MarkupSafe==2.0.1
9+
requests==2.26.0
10+
urllib3==1.26.7
11+
Werkzeug==2.0.1
12+
workos==1.4.0
13+
python-dotenv
Binary file not shown.

0 commit comments

Comments
 (0)