-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauth_example.py
executable file
·139 lines (116 loc) · 5.5 KB
/
auth_example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 17 16:44:23 2017
@author: liming
"""
from flask import Flask, url_for, session, redirect, request
import globus_sdk
import json
app = Flask(__name__)
app.config.from_pyfile('auth_example.conf')
def load_app_client():
return globus_sdk.ConfidentialAppAuthClient(
app.config['APP_CLIENT_ID'], app.config['APP_CLIENT_SECRET'])
@app.route("/", methods=['GET'])
def index():
"""
This could be any page you like, rendered by Flask.
For this simple example, it will either redirect you to login, or print
a simple message.
"""
if not session.get('is_authenticated'):
return redirect(url_for('login'))
logout_uri = url_for('logout', _external=True)
# get the stored access token for the Auth API and use it
# to authorize stuff AS THE AUTHENTICATED USER
auth_token = str(session.get('tokens')['auth.globus.org']['access_token'])
ac = globus_sdk.AuthClient(authorizer=globus_sdk.AccessTokenAuthorizer(auth_token))
# use Auth API to get more info about the authenticated user
myids = ac.get_identities(ids=str(session.get('username')),include="identity_provider").data
# use Auth API to get the standard OIDC userinfo fields (like any OIDC client)
oidcinfo = ac.oauth2_userinfo()
# get the stored OIDC id_token
myoidc = session.get('id_token')
# authenticate to Auth API AS AN APPLICATION and find out still more information
cc = load_app_client()
ir = cc.oauth2_token_introspect(auth_token,include='identities_set').data
# display all this information on the web page
page = '<html>\n<head><title>Display Your Auth Data</title></head>\n\n'
page = page + '<body>\n<p>' + str(session.get('realname')) + ', you are logged in.</p>\n\n'
page = page + '<p>Your local username is: ' + str(session.get('username')) + '</p>\n\n'
page = page + '<p><a href="'+logout_uri+'">Logout now.</a></p>\n\n'
page = page + '<p>OIDC UserInfo says your effective ID is ' + oidcinfo["sub"]
page = page + ', your name is ' + oidcinfo["name"]
page = page + ', and your email is ' + oidcinfo["email"] + '.</p>\n\n'
page = page + '<pre>' + json.dumps(oidcinfo.data,indent=3) + '</pre>\n\n'
page = page + '<p>Your OIDC identity is:</p>\n<pre>' + json.dumps(myoidc,indent=3) + '</pre>\n\n'
page = page + '<p>Your Globus Auth identity is:</p>\n<pre>' + json.dumps(myids,indent=3) + '</pre>\n\n'
page = page + '<p>Introspecting your Auth API access token tells me:</p>\n<pre>' + json.dumps(ir,indent=3) + '</pre>\n\n'
# We probably shouldn't display the token, but for debugging purposes, here's how you'd do it...
# page = page + '<p>The tokens I received are:</p>\n<pre>' + json.dumps(session.get('tokens'),indent=3) + '</pre>\n\n'
page = page + '</body></html>'
return(page)
@app.route("/login", methods=['GET'])
def login():
"""
Login via Globus Auth.
May be invoked in one of two scenarios:
1. Login is starting, no state in Globus Auth yet
2. Returning to application during login, already have short-lived
code from Globus Auth to exchange for tokens, encoded in a query
param
"""
# the redirect URI, as a complete URI (not relative path)
redirect_uri = url_for('login', _external=True)
auth_client = load_app_client()
auth_client.oauth2_start_flow(redirect_uri,
requested_scopes='openid email profile urn:globus:auth:scope:auth.globus.org:view_identity_set')
# If there's no "code" query string parameter, we're in this route
# starting a Globus Auth login flow.
# Redirect out to Globus Auth
if 'code' not in request.args:
auth_uri = auth_client.oauth2_get_authorize_url()
return redirect(auth_uri)
# If we do have a "code" param, we're coming back from Globus Auth
# and can start the process of exchanging an auth code for a token.
else:
code = request.args.get('code')
tokens_response = auth_client.oauth2_exchange_code_for_tokens(code)
ids = tokens_response.decode_id_token(auth_client)
session.update(
tokens=tokens_response.by_resource_server,
id_token=ids,
username=ids['sub'],
realname=ids['name'],
is_authenticated=True
)
return redirect(url_for('index'))
@app.route("/logout", methods=['GET'])
def logout():
"""
- Revoke the tokens with Globus Auth.
- Destroy the session state.
- Redirect the user to the Globus Auth logout page.
"""
client = load_app_client()
# Revoke the tokens with Globus Auth
for token in (token_info['access_token']
for token_info in session['tokens'].values()):
client.oauth2_revoke_token(token)
# Destroy the session state
session.clear()
# the return redirection location to give to Globus AUth
redirect_uri = url_for('index', _external=True)
# build the logout URI with query params
# there is no tool to help build this (yet!)
globus_logout_url = (
'https://auth.globus.org/v2/web/logout' +
'?client={}'.format(app.config['APP_CLIENT_ID']) +
'&redirect_uri={}'.format(redirect_uri) +
'&redirect_name=Your Flask App')
# Redirect the user to the Globus Auth logout page
return redirect(globus_logout_url)
# actually run the app if this is called as a script
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000,debug=True,ssl_context=('./keys/server.crt', './keys/server.key'))