/atom/token_store.py
http://radioappz.googlecode.com/ · Python · 117 lines · 40 code · 14 blank · 63 comment · 14 complexity · c49443de339d8a40c79d10b537c9c346 MD5 · raw file
- #!/usr/bin/python
- #
- # Copyright (C) 2008 Google Inc.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """This module provides a TokenStore class which is designed to manage
- auth tokens required for different services.
- Each token is valid for a set of scopes which is the start of a URL. An HTTP
- client will use a token store to find a valid Authorization header to send
- in requests to the specified URL. If the HTTP client determines that a token
- has expired or been revoked, it can remove the token from the store so that
- it will not be used in future requests.
- """
- __author__ = 'api.jscudder (Jeff Scudder)'
- import atom.http_interface
- import atom.url
- SCOPE_ALL = 'http'
- class TokenStore(object):
- """Manages Authorization tokens which will be sent in HTTP headers."""
- def __init__(self, scoped_tokens=None):
- self._tokens = scoped_tokens or {}
- def add_token(self, token):
- """Adds a new token to the store (replaces tokens with the same scope).
- Args:
- token: A subclass of http_interface.GenericToken. The token object is
- responsible for adding the Authorization header to the HTTP request.
- The scopes defined in the token are used to determine if the token
- is valid for a requested scope when find_token is called.
- Returns:
- True if the token was added, False if the token was not added becase
- no scopes were provided.
- """
- if not hasattr(token, 'scopes') or not token.scopes:
- return False
- for scope in token.scopes:
- self._tokens[str(scope)] = token
- return True
- def find_token(self, url):
- """Selects an Authorization header token which can be used for the URL.
- Args:
- url: str or atom.url.Url or a list containing the same.
- The URL which is going to be requested. All
- tokens are examined to see if any scopes begin match the beginning
- of the URL. The first match found is returned.
- Returns:
- The token object which should execute the HTTP request. If there was
- no token for the url (the url did not begin with any of the token
- scopes available), then the atom.http_interface.GenericToken will be
- returned because the GenericToken calls through to the http client
- without adding an Authorization header.
- """
- if url is None:
- return None
- if isinstance(url, (str, unicode)):
- url = atom.url.parse_url(url)
- if url in self._tokens:
- token = self._tokens[url]
- if token.valid_for_scope(url):
- return token
- else:
- del self._tokens[url]
- for scope, token in self._tokens.iteritems():
- if token.valid_for_scope(url):
- return token
- return atom.http_interface.GenericToken()
- def remove_token(self, token):
- """Removes the token from the token_store.
- This method is used when a token is determined to be invalid. If the
- token was found by find_token, but resulted in a 401 or 403 error stating
- that the token was invlid, then the token should be removed to prevent
- future use.
- Returns:
- True if a token was found and then removed from the token
- store. False if the token was not in the TokenStore.
- """
- token_found = False
- scopes_to_delete = []
- for scope, stored_token in self._tokens.iteritems():
- if stored_token == token:
- scopes_to_delete.append(scope)
- token_found = True
- for scope in scopes_to_delete:
- del self._tokens[scope]
- return token_found
- def remove_all_tokens(self):
- self._tokens = {}