"Fossies" - the Fresh Open Source Software Archive

Member "keystone-17.0.0/keystone/oauth1/validator.py" (13 May 2020, 8860 Bytes) of package /linux/misc/openstack/keystone-17.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "validator.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 16.0.1_vs_17.0.0.

    1 # Copyright 2014 OpenStack Foundation
    2 #
    3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 # not use this file except in compliance with the License. You may obtain
    5 # a copy of the License at
    6 #
    7 #      http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 # Unless required by applicable law or agreed to in writing, software
   10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 # License for the specific language governing permissions and limitations
   13 # under the License.
   14 
   15 """oAuthlib request validator."""
   16 
   17 from keystone.common import provider_api
   18 from keystone import exception
   19 from keystone.oauth1.backends import base
   20 from keystone.oauth1 import core as oauth1
   21 
   22 
   23 METHOD_NAME = 'oauth_validator'
   24 PROVIDERS = provider_api.ProviderAPIs
   25 
   26 
   27 class OAuthValidator(provider_api.ProviderAPIMixin, oauth1.RequestValidator):
   28 
   29     # TODO(mhu) set as option probably?
   30     @property
   31     def enforce_ssl(self):
   32         return False
   33 
   34     @property
   35     def safe_characters(self):
   36         # oauth tokens are generated from a uuid hex value
   37         return set("abcdef0123456789")
   38 
   39     def _check_token(self, token):
   40         # generic token verification when they're obtained from a uuid hex
   41         return (set(token) <= self.safe_characters and
   42                 len(token) == 32)
   43 
   44     def check_client_key(self, client_key):
   45         return self._check_token(client_key)
   46 
   47     def check_request_token(self, request_token):
   48         return self._check_token(request_token)
   49 
   50     def check_access_token(self, access_token):
   51         return self._check_token(access_token)
   52 
   53     def check_nonce(self, nonce):
   54         # Assuming length is not a concern
   55         return set(nonce) <= self.safe_characters
   56 
   57     def check_verifier(self, verifier):
   58         return (all(i in base.VERIFIER_CHARS for i in verifier) and
   59                 len(verifier) == 8)
   60 
   61     def get_client_secret(self, client_key, request):
   62         client = PROVIDERS.oauth_api.get_consumer_with_secret(client_key)
   63         return client['secret']
   64 
   65     def get_request_token_secret(self, client_key, token, request):
   66         token_ref = PROVIDERS.oauth_api.get_request_token(token)
   67         return token_ref['request_secret']
   68 
   69     def get_access_token_secret(self, client_key, token, request):
   70         access_token = PROVIDERS.oauth_api.get_access_token(token)
   71         return access_token['access_secret']
   72 
   73     def get_default_realms(self, client_key, request):
   74         # realms weren't implemented with the previous library
   75         return []
   76 
   77     def get_realms(self, token, request):
   78         return []
   79 
   80     def get_redirect_uri(self, token, request):
   81         # OOB (out of band) is supposed to be the default value to use
   82         return 'oob'
   83 
   84     def get_rsa_key(self, client_key, request):
   85         # HMAC signing is used, so return a dummy value
   86         return ''
   87 
   88     def invalidate_request_token(self, client_key, request_token, request):
   89         """Invalidate a used request token.
   90 
   91         :param client_key: The client/consumer key.
   92         :param request_token: The request token string.
   93         :param request: An oauthlib.common.Request object.
   94         :returns: None
   95 
   96         Per `Section 2.3`_ of the spec:
   97 
   98         "The server MUST (...) ensure that the temporary
   99         credentials have not expired or been used before."
  100 
  101         .. _`Section 2.3`: https://tools.ietf.org/html/rfc5849#section-2.3
  102 
  103         This method should ensure that provided token won't validate anymore.
  104         It can be simply removing RequestToken from storage or setting
  105         specific flag that makes it invalid (note that such flag should be
  106         also validated during request token validation).
  107 
  108         This method is used by
  109 
  110         * AccessTokenEndpoint
  111         """
  112         # FIXME(lbragstad): Remove the above documentation string once
  113         # https://bugs.launchpad.net/keystone/+bug/1778603 is resolved. It is
  114         # being duplicated here to work around oauthlib compatibility issues
  115         # with Sphinx 1.7.5, which have been reported upstream in
  116         # https://github.com/oauthlib/oauthlib/issues/558.
  117 
  118         # this method is invoked when an access token is generated out of a
  119         # request token, to make sure that request token cannot be consumed
  120         # anymore. This is done in the backend, so we do nothing here.
  121         pass
  122 
  123     def validate_client_key(self, client_key, request):
  124         try:
  125             return PROVIDERS.oauth_api.get_consumer(client_key) is not None
  126         except exception.NotFound:
  127             return False
  128 
  129     def validate_request_token(self, client_key, token, request):
  130         try:
  131             req_token = PROVIDERS.oauth_api.get_request_token(token)
  132             if req_token:
  133                 return req_token['consumer_id'] == client_key
  134             else:
  135                 return False
  136         except exception.NotFound:
  137             return False
  138 
  139     def validate_access_token(self, client_key, token, request):
  140         try:
  141             return PROVIDERS.oauth_api.get_access_token(token) is not None
  142         except exception.NotFound:
  143             return False
  144 
  145     def validate_timestamp_and_nonce(self,
  146                                      client_key,
  147                                      timestamp,
  148                                      nonce,
  149                                      request,
  150                                      request_token=None,
  151                                      access_token=None):
  152         return True
  153 
  154     def validate_redirect_uri(self, client_key, redirect_uri, request):
  155         # we expect OOB, we don't really care
  156         return True
  157 
  158     def validate_requested_realms(self, client_key, realms, request):
  159         # realms are not used
  160         return True
  161 
  162     def validate_realms(self,
  163                         client_key,
  164                         token,
  165                         request,
  166                         uri=None,
  167                         realms=None):
  168         return True
  169 
  170     def validate_verifier(self, client_key, token, verifier, request):
  171         try:
  172             req_token = PROVIDERS.oauth_api.get_request_token(token)
  173             return req_token['verifier'] == verifier
  174         except exception.NotFound:
  175             return False
  176 
  177     def verify_request_token(self, token, request):
  178         # there aren't strong expectations on the request token format
  179         return isinstance(token, str)
  180 
  181     def verify_realms(self, token, realms, request):
  182         return True
  183 
  184     # The following save_XXX methods are called to create tokens. I chose to
  185     # keep the original logic, but the comments below show how that could be
  186     # implemented. The real implementation logic is in the backend.
  187     def save_access_token(self, token, request):
  188         pass
  189 #        token_duration = CONF.oauth1.request_token_duration
  190 #        request_token_id = request.client_key
  191 #        self.oauth_api.create_access_token(request_token_id,
  192 #                                           token_duration,
  193 #                                           token["oauth_token"],
  194 #                                           token["oauth_token_secret"])
  195 
  196     def save_request_token(self, token, request):
  197         pass
  198 #        project_id = request.headers.get('Requested-Project-Id')
  199 #        token_duration = CONF.oauth1.request_token_duration
  200 #        self.oauth_api.create_request_token(request.client_key,
  201 #                                            project_id,
  202 #                                            token_duration,
  203 #                                            token["oauth_token"],
  204 #                                            token["oauth_token_secret"])
  205 
  206     def save_verifier(self, token, verifier, request):
  207         """Associate an authorization verifier with a request token.
  208 
  209         :param token: A request token string.
  210         :param verifier: A dictionary containing the oauth_verifier and
  211                          oauth_token
  212         :param request: An oauthlib.common.Request object.
  213 
  214         We need to associate verifiers with tokens for validation during the
  215         access token request.
  216 
  217         Note that unlike save_x_token token here is the ``oauth_token`` token
  218         string from the request token saved previously.
  219 
  220         This method is used by
  221 
  222         * AuthorizationEndpoint
  223         """
  224         # FIXME(lbragstad): Remove the above documentation string once
  225         # https://bugs.launchpad.net/keystone/+bug/1778603 is resolved. It is
  226         # being duplicated here to work around oauthlib compatibility issues
  227         # with Sphinx 1.7.5, which have been reported upstream in
  228         # https://github.com/oauthlib/oauthlib/issues/558.
  229 
  230         # keep the old logic for this, as it is done in two steps and requires
  231         # information that the request validator has no access to
  232         pass