PageRenderTime 24ms CodeModel.GetById 19ms app.highlight 2ms RepoModel.GetById 2ms app.codeStats 0ms

/atom/token_store.py

http://radioappz.googlecode.com/
Python | 117 lines | 40 code | 14 blank | 63 comment | 20 complexity | c49443de339d8a40c79d10b537c9c346 MD5 | raw file
  1#!/usr/bin/python
  2#
  3# Copyright (C) 2008 Google Inc.
  4#
  5# Licensed under the Apache License, Version 2.0 (the "License");
  6# you may not use this file except in compliance with the License.
  7# You may obtain a copy of the License at
  8#
  9#      http://www.apache.org/licenses/LICENSE-2.0
 10#
 11# Unless required by applicable law or agreed to in writing, software
 12# distributed under the License is distributed on an "AS IS" BASIS,
 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14# See the License for the specific language governing permissions and
 15# limitations under the License.
 16
 17"""This module provides a TokenStore class which is designed to manage
 18auth tokens required for different services.
 19
 20Each token is valid for a set of scopes which is the start of a URL. An HTTP
 21client will use a token store to find a valid Authorization header to send
 22in requests to the specified URL. If the HTTP client determines that a token
 23has expired or been revoked, it can remove the token from the store so that
 24it will not be used in future requests.
 25"""
 26
 27
 28__author__ = 'api.jscudder (Jeff Scudder)'
 29
 30
 31import atom.http_interface
 32import atom.url
 33
 34
 35SCOPE_ALL = 'http'
 36
 37
 38class TokenStore(object):
 39  """Manages Authorization tokens which will be sent in HTTP headers."""
 40  def __init__(self, scoped_tokens=None):
 41    self._tokens = scoped_tokens or {}
 42
 43  def add_token(self, token):
 44    """Adds a new token to the store (replaces tokens with the same scope).
 45
 46    Args:
 47      token: A subclass of http_interface.GenericToken. The token object is 
 48          responsible for adding the Authorization header to the HTTP request.
 49          The scopes defined in the token are used to determine if the token
 50          is valid for a requested scope when find_token is called.
 51
 52    Returns:
 53      True if the token was added, False if the token was not added becase
 54      no scopes were provided.
 55    """
 56    if not hasattr(token, 'scopes') or not token.scopes:
 57      return False
 58
 59    for scope in token.scopes:
 60      self._tokens[str(scope)] = token
 61    return True  
 62
 63  def find_token(self, url):
 64    """Selects an Authorization header token which can be used for the URL.
 65
 66    Args:
 67      url: str or atom.url.Url or a list containing the same.
 68          The URL which is going to be requested. All
 69          tokens are examined to see if any scopes begin match the beginning
 70          of the URL. The first match found is returned.
 71
 72    Returns:
 73      The token object which should execute the HTTP request. If there was
 74      no token for the url (the url did not begin with any of the token
 75      scopes available), then the atom.http_interface.GenericToken will be 
 76      returned because the GenericToken calls through to the http client
 77      without adding an Authorization header.
 78    """
 79    if url is None:
 80      return None
 81    if isinstance(url, (str, unicode)):
 82      url = atom.url.parse_url(url)
 83    if url in self._tokens:
 84      token = self._tokens[url]
 85      if token.valid_for_scope(url):
 86        return token
 87      else:
 88        del self._tokens[url]
 89    for scope, token in self._tokens.iteritems():
 90      if token.valid_for_scope(url):
 91        return token
 92    return atom.http_interface.GenericToken()
 93
 94  def remove_token(self, token):
 95    """Removes the token from the token_store.
 96
 97    This method is used when a token is determined to be invalid. If the
 98    token was found by find_token, but resulted in a 401 or 403 error stating
 99    that the token was invlid, then the token should be removed to prevent
100    future use.
101
102    Returns:
103      True if a token was found and then removed from the token
104      store. False if the token was not in the TokenStore.
105    """
106    token_found = False
107    scopes_to_delete = []
108    for scope, stored_token in self._tokens.iteritems():
109      if stored_token == token:
110        scopes_to_delete.append(scope)
111        token_found = True
112    for scope in scopes_to_delete:
113      del self._tokens[scope]
114    return token_found
115
116  def remove_all_tokens(self):
117    self._tokens = {}