@@ -97,7 +97,7 @@ def set_login_cookie(cls, handler, user_id=None):
97
97
auth_header_pat = re .compile ('token\s+(.+)' , re .IGNORECASE )
98
98
99
99
@classmethod
100
- def get_user_token (cls , handler ):
100
+ def get_token (cls , handler ):
101
101
"""Get the user token from a request
102
102
103
103
Default:
@@ -117,14 +117,29 @@ def get_user_token(cls, handler):
117
117
@classmethod
118
118
def should_check_origin (cls , handler ):
119
119
"""Should the Handler check for CORS origin validation?
120
-
120
+
121
121
Origin check should be skipped for token-authenticated requests.
122
+
123
+ Returns:
124
+ - True, if Handler must check for valid CORS origin.
125
+ - False, if Handler should skip origin check since requests are token-authenticated.
126
+ """
127
+ return not cls .is_token_authenticated (handler )
128
+
129
+ @classmethod
130
+ def is_token_authenticated (cls , handler ):
131
+ """Returns True if handler has been token authenticated. Otherwise, False.
132
+
133
+ Login with a token is used to signal certain things, such as:
134
+
135
+ - permit access to REST API
136
+ - xsrf protection
137
+ - skip origin-checks for scripts
122
138
"""
123
139
if getattr (handler , '_user_id' , None ) is None :
124
140
# ensure get_user has been called, so we know if we're token-authenticated
125
141
handler .get_current_user ()
126
- token_authenticated = getattr (handler , '_token_authenticated' , False )
127
- return not token_authenticated
142
+ return getattr (handler , '_token_authenticated' , False )
128
143
129
144
@classmethod
130
145
def get_user (cls , handler ):
@@ -136,40 +151,56 @@ def get_user(cls, handler):
136
151
# called on LoginHandler itself.
137
152
if getattr (handler , '_user_id' , None ):
138
153
return handler ._user_id
139
- user_id = handler .get_secure_cookie (handler .cookie_name )
140
- if not user_id :
154
+ user_id = cls .get_user_token (handler )
155
+ if user_id is None :
156
+ user_id = handler .get_secure_cookie (handler .cookie_name )
157
+ else :
158
+ cls .set_login_cookie (handler , user_id )
159
+ # Record that the current request has been authenticated with a token.
160
+ # Used in is_token_authenticated above.
161
+ handler ._token_authenticated = True
162
+ if user_id is None :
141
163
# prevent extra Invalid cookie sig warnings:
142
164
handler .clear_login_cookie ()
143
- token = handler .token
144
- if not token and not handler .login_available :
165
+ if not handler .login_available :
145
166
# Completely insecure! No authentication at all.
146
167
# No need to warn here, though; validate_security will have already done that.
147
- return 'anonymous'
148
- if token :
149
- # check login token from URL argument or Authorization header
150
- user_token = cls .get_user_token (handler )
151
- one_time_token = handler .one_time_token
152
- authenticated = False
153
- if user_token == token :
154
- # token-authenticated, set the login cookie
155
- handler .log .info ("Accepting token-authenticated connection from %s" , handler .request .remote_ip )
156
- authenticated = True
157
- elif one_time_token and user_token == one_time_token :
158
- # one-time-token-authenticated, only allow this token once
159
- handler .settings .pop ('one_time_token' , None )
160
- handler .log .info ("Accepting one-time-token-authenticated connection from %s" , handler .request .remote_ip )
161
- authenticated = True
162
- if authenticated :
163
- user_id = uuid .uuid4 ().hex
164
- cls .set_login_cookie (handler , user_id )
165
- # Record that we've been authenticated with a token.
166
- # Used in should_check_origin above.
167
- handler ._token_authenticated = True
168
+ user_id = 'anonymous'
168
169
169
170
# cache value for future retrievals on the same request
170
171
handler ._user_id = user_id
171
172
return user_id
172
173
174
+ @classmethod
175
+ def get_user_token (cls , handler ):
176
+ """Identify the user based on a token in the URL or Authorization header
177
+
178
+ Returns:
179
+ - uuid if authenticated
180
+ - None if not
181
+ """
182
+ token = handler .token
183
+ if not token :
184
+ return
185
+ # check login token from URL argument or Authorization header
186
+ user_token = cls .get_token (handler )
187
+ one_time_token = handler .one_time_token
188
+ authenticated = False
189
+ if user_token == token :
190
+ # token-authenticated, set the login cookie
191
+ handler .log .debug ("Accepting token-authenticated connection from %s" , handler .request .remote_ip )
192
+ authenticated = True
193
+ elif one_time_token and user_token == one_time_token :
194
+ # one-time-token-authenticated, only allow this token once
195
+ handler .settings .pop ('one_time_token' , None )
196
+ handler .log .info ("Accepting one-time-token-authenticated connection from %s" , handler .request .remote_ip )
197
+ authenticated = True
198
+
199
+ if authenticated :
200
+ return uuid .uuid4 ().hex
201
+ else :
202
+ return None
203
+
173
204
174
205
@classmethod
175
206
def validate_security (cls , app , ssl_options = None ):
0 commit comments