Skip to content

Commit 9285f9d

Browse files
authored
Merge pull request #2 from reflex-dev/masenf/iframe-auth
iframe compatibility and extended token validation
2 parents 2f45b99 + 488f749 commit 9285f9d

File tree

13 files changed

+881
-533
lines changed

13 files changed

+881
-533
lines changed

README.md

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ Reflex will need to access these variables to authenticate users via OpenID Conn
3131
- Redirect URI: add the authorization callback path for your app, e.g. `https://your-app.example.com/authorization-code/callback` (use `http://localhost:3000/authorization-code/callback` for local development).
3232
3. Register the app and copy the "Application (client) ID" → this is `AZURE_CLIENT_ID`.
3333
4. Under "Certificates & secrets" create a new client secret and copy the value → this is `AZURE_CLIENT_SECRET`.
34-
5. Under "Expose an API" or "API permissions" add the scopes your app needs. For typical OpenID Connect sign-in, request the `openid`, `profile`, and `email` scopes. If you need access to a custom API, expose an application ID URI (e.g. `api://<client-id>`) and create delegated scopes.
35-
6. Determine your issuer (authority) URL:
36-
- For a single tenant: `https://login.microsoftonline.com/<your-tenant-id>`
37-
- For common/multi-tenant flows: `https://login.microsoftonline.com/common`
38-
Use the `AZURE_ISSUER_URI` env var to set this (you can include the `/v2.0` suffix or we default to `v2.0` for endpoint assembly).
34+
5. Under "Expose an API" or "API permissions" add the scopes your app needs. For typical OpenID Connect sign-in, request the `openid`, `profile`, and `email` scopes.
35+
6. Determine your issuer (authority) URL as `AZURE_ISSUER_URI` env var.
36+
- For a single tenant: `https://login.microsoftonline.com/<your-tenant-id>/v2.0`
37+
- For common/multi-tenant flows: `https://login.microsoftonline.com/common/v2.0`
38+
7. For multi-tenant apps, you can use the `AZURE_VALID_TENANT_IDS` env var to specify which comma-separated tenant IDs are allowed.
3939

4040
Example .env (local development):
4141

4242
```env
4343
AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
4444
AZURE_CLIENT_SECRET=very-secret-value
45-
AZURE_ISSUER_URI=https://login.microsoftonline.com/common
46-
AZURE_AUDIENCE=api://default
45+
AZURE_ISSUER_URI=https://login.microsoftonline.com/consumers/v2.0
46+
AZURE_VALID_TENANT_IDS=00000000-0000-0000-0000-000000000000,9188040d-6c67-4c5b-b112-36a304b66dad
4747
```
4848

4949
Notes:
@@ -65,9 +65,11 @@ register_auth_endpoints(app)
6565

6666
### Check `AzureAuthState.userinfo` for user identity/validity
6767

68+
To fully support embedded/iframe apps, be sure to wrap your login button with `azure_login_button`.
69+
6870
```python
6971
import reflex as rx
70-
from reflex_azure_auth import AzureAuthState
72+
from reflex_azure_auth import AzureAuthState, azure_login_button
7173

7274
@rx.page()
7375
def index():
@@ -83,7 +85,9 @@ def index():
8385
rx.text(AzureAuthState.userinfo.to_string()),
8486
rx.button("Logout", on_click=AzureAuthState.redirect_to_logout),
8587
),
86-
rx.button("Log In with Microsoft", on_click=AzureAuthState.redirect_to_login),
88+
azure_login_button(
89+
rx.button("Log In with Microsoft"),
90+
),
8791
),
8892
rx.spinner(),
8993
),
@@ -97,3 +101,28 @@ tokens to ensure they have not been tampered with. Use
97101
Before performing privileged backend operations, it is important to validate the
98102
tokens to ensure they have not been tampered with. Use
99103
`AzureAuthState._validate_tokens()` helper method to validate the tokens.
104+
105+
### Customize the UI
106+
107+
The `register_auth_endpoints` function accepts 3 optional UI callables:
108+
109+
#### `loading_page`
110+
111+
This is the page displayed before and after redirecting to the Azure authorization endpoint.
112+
113+
The default implementation uses `rx.cond(~rx.State.is_hydrated | ~AzureAuthState.userinfo, ...)`
114+
to show a different message based on whether the user info was fetched or not.
115+
116+
#### `popup_login_page`
117+
118+
When the app is within an iframe, the normal redirect flow cannot be used, so
119+
the authentication is handled within a popup window. This callable returns the
120+
page displayed in the popup window before and after redirecting to the Azure
121+
authorization endpoint.
122+
123+
#### `popup_logout_page`
124+
125+
When the app is within an iframe, the normal redirect flow cannot be used, so
126+
the authentication is handled within a popup window. This callable returns the
127+
page displayed in the popup window before redirecting to the Azure
128+
logout endpoint.

demos/azure/azure.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
import reflex as rx
44
import reflex_enterprise as rxe
55

6-
from reflex_azure_auth import AzureAuthState, register_auth_endpoints
6+
from reflex_azure_auth import (
7+
AzureAuthState,
8+
azure_login_button,
9+
register_auth_endpoints,
10+
)
711

812

913
def index():
14+
"""Main page component for the demo app."""
1015
return rx.container(
1116
rx.vstack(
1217
rx.heading("Azure (Microsoft) Auth Demo"),
@@ -15,13 +20,16 @@ def index():
1520
rx.cond(
1621
AzureAuthState.userinfo,
1722
rx.vstack(
18-
rx.text(f"Welcome, {AzureAuthState.userinfo['name']}!"),
23+
rx.text(
24+
f"Welcome, {AzureAuthState.userinfo.get('name', AzureAuthState.userinfo.get('given_name'))}!"
25+
),
1926
rx.text(AzureAuthState.userinfo.to_string()),
2027
rx.button("Logout", on_click=AzureAuthState.redirect_to_logout),
2128
),
22-
rx.button(
23-
"Log In with Microsoft",
24-
on_click=AzureAuthState.redirect_to_login,
29+
azure_login_button(
30+
rx.button(
31+
"Log In with Microsoft",
32+
),
2533
),
2634
),
2735
rx.spinner(),

0 commit comments

Comments
 (0)