コード例 #1
0
def _discovery(request):
    """Returns a JSON file listing the services supported by the server."""
    services = request.registry.settings['tokenserver.applications']
    discovery = {}
    discovery["services"] = services
    discovery["auth"] = request.url.rstrip("/")
    try:
        verifier = get_browserid_verifier(request.registry)
    except ComponentLookupError:
        pass
    else:
        discovery["browserid"] = {
            "allowed_issuers": verifier.allowed_issuers,
            "trusted_issuers": verifier.trusted_issuers,
        }
    try:
        verifier = get_oauth_verifier(request.registry)
    except ComponentLookupError:
        pass
    else:
        discovery["oauth"] = {
            "default_issuer": verifier.default_issuer,
            "scope": verifier.scope,
            "server_url": verifier.server_url,
        }
    return discovery
コード例 #2
0
ファイル: views.py プロジェクト: mozilla-services/tokenserver
def _discovery(request):
    """Returns a JSON file listing the services supported by the server."""
    services = request.registry.settings['tokenserver.applications']
    discovery = {}
    discovery["services"] = services
    discovery["auth"] = request.url.rstrip("/")
    try:
        verifier = get_browserid_verifier(request.registry)
    except ComponentLookupError:
        pass
    else:
        discovery["browserid"] = {
          "allowed_issuers": verifier.allowed_issuers,
          "trusted_issuers": verifier.trusted_issuers,
        }
    try:
        verifier = get_oauth_verifier(request.registry)
    except ComponentLookupError:
        pass
    else:
        discovery["oauth"] = {
          "default_issuer": verifier.default_issuer,
          "scope": verifier.scope,
          "server_url": verifier.server_url,
        }
    return discovery
コード例 #3
0
ファイル: views.py プロジェクト: mozilla-services/tokenserver
def _validate_oauth_token(request, token):
    try:
        verifier = get_oauth_verifier(request.registry)
    except ComponentLookupError:
        raise _unauthorized(description='Unsupported')
    try:
        with metrics_timer('tokenserver.oauth.verify', request):
            token = verifier.verify(token)
    except (fxa.errors.Error, ConnectionError) as e:
        request.metrics['token.oauth.verify_failure'] = 1
        if isinstance(e, fxa.errors.InProtocolError):
            request.metrics['token.oauth.errno.%s' % e.errno] = 1
        # Log a full traceback for errors that are not a simple
        # "your token was bad and we dont trust it".
        if not isinstance(e, fxa.errors.TrustError):
            if not isinstance(e, fxa.errors.InProtocolError):
                logger.exception("Unexpected verification error")
            elif e.errno not in OAUTH_EXPECTED_ERRNOS:
                logger.exception("Unexpected verification error")
        # Report an appropriate error code.
        if isinstance(e, ConnectionError):
            request.metrics['token.oauth.connection_error'] = 1
            raise json_error(503, description="Resource is not available")
        raise _unauthorized("invalid-credentials")

    request.metrics['token.oauth.verify_success'] = 1
    request.validated['authorization'] = token

    # OAuth clients should send the scoped-key kid in lieu of X-Client-State.
    # A future enhancement might allow us to learn this from the OAuth
    # verification response rather than requiring a separate header.
    kid = request.headers.get('X-KeyID')
    if kid:
        try:
            # The kid combines a timestamp and a hash of the key material,
            # so we can decode it into equivalent information to what we
            # get out of a BrowserID assertion.
            generation, client_state = kid.split("-", 1)
            generation = int(generation)
            idpClaims = request.validated['authorization']['idpClaims']
            idpClaims['fxa-generation'] = generation
            client_state = browserid.utils.decode_bytes(client_state)
            client_state = client_state.encode('hex')
            if not 1 <= len(client_state) <= 32:
                raise json_error(400, location='header', name='X-Client-State',
                                 description='Invalid client state value')
            # Sanity-check in case the client sent *both* headers.
            # If they don't match, the client is definitely confused.
            if 'X-Client-State' in request.headers:
                if request.headers['X-Client-State'] != client_state:
                    raise _unauthorized("invalid-client-state")
            request.validated['client-state'] = client_state
        except (IndexError, ValueError):
            raise _unauthorized("invalid-credentials")
コード例 #4
0
def _validate_oauth_token(request, token):
    try:
        verifier = get_oauth_verifier(request.registry)
    except ComponentLookupError:
        raise _unauthorized(description='Unsupported')
    try:
        with metrics_timer('tokenserver.oauth.verify', request):
            token = verifier.verify(token)
    except (fxa.errors.Error, ConnectionError) as e:
        request.metrics['token.oauth.verify_failure'] = 1
        if isinstance(e, fxa.errors.InProtocolError):
            request.metrics['token.oauth.errno.%s' % e.errno] = 1
        # Log a full traceback for errors that are not a simple
        # "your token was bad and we dont trust it".
        if not isinstance(e, fxa.errors.TrustError):
            logger.exception("Unexpected verification error")
        # Report an appropriate error code.
        if isinstance(e, ConnectionError):
            request.metrics['token.oauth.connection_error'] = 1
            raise json_error(503, description="Resource is not available")
        raise _unauthorized("invalid-credentials")

    request.metrics['token.oauth.verify_success'] = 1
    request.validated['authorization'] = token

    # OAuth clients should send the scoped-key kid in lieu of X-Client-State.
    # A future enhancement might allow us to learn this from the OAuth
    # verification response rather than requiring a separate header.
    kid = request.headers.get('X-KeyID')
    if kid:
        try:
            # The kid combines a timestamp and a hash of the key material,
            # so we can decode it into equivalent information to what we
            # get out of a BrowserID assertion.
            generation, client_state = kid.split("-", 1)
            generation = int(generation)
            idpClaims = request.validated['authorization']['idpClaims']
            idpClaims['fxa-generation'] = generation
            client_state = browserid.utils.decode_bytes(client_state)
            client_state = client_state.encode('hex')
            if not 1 <= len(client_state) <= 32:
                raise json_error(400,
                                 location='header',
                                 name='X-Client-State',
                                 description='Invalid client state value')
            # Sanity-check in case the client sent *both* headers.
            # If they don't match, the client is definitely confused.
            if 'X-Client-State' in request.headers:
                if request.headers['X-Client-State'] != client_state:
                    raise _unauthorized("invalid-client-state")
            request.validated['client-state'] = client_state
        except (IndexError, ValueError):
            raise _unauthorized("invalid-credentials")
コード例 #5
0
 def mock_oauth_verifier(self, response=None, exc=None):
     def mock_verify_method(token):
         if exc is not None:
             raise exc
         if response is not None:
             return response
         return {
             "email": token.decode("hex"),
             "idpClaims": {},
         }
     verifier = get_oauth_verifier(self.config.registry)
     orig_verify_method = verifier.__dict__.get("verify", None)
     verifier.__dict__["verify"] = mock_verify_method
     try:
         yield None
     finally:
         if orig_verify_method is None:
             del verifier.__dict__["verify"]
         else:
             verifier.__dict__["verify"] = orig_verify_method
コード例 #6
0
 def mock_oauth_verifier(self, response=None, exc=None):
     def mock_verify_method(token):
         if exc is not None:
             raise exc
         if response is not None:
             return response
         return {
             "email": token.decode("hex"),
             "idpClaims": {},
         }
     verifier = get_oauth_verifier(self.config.registry)
     orig_verify_method = verifier.__dict__.get("verify", None)
     verifier.__dict__["verify"] = mock_verify_method
     try:
         yield None
     finally:
         if orig_verify_method is None:
             del verifier.__dict__["verify"]
         else:
             verifier.__dict__["verify"] = orig_verify_method
コード例 #7
0
ファイル: views.py プロジェクト: autrilla/tokenserver
def _valid_oauth_token(request, token):
    try:
        verifier = get_oauth_verifier(request.registry)
        with metrics_timer('tokenserver.oauth.verify', request):
            token = verifier.verify(token)
    except (fxa.errors.Error, ConnectionError) as e:
        request.metrics['token.oauth.verify_failure'] = 1
        if isinstance(e, fxa.errors.InProtocolError):
            request.metrics['token.oauth.errno.%s' % e.errno] = 1
        # Log a full traceback for errors that are not a simple
        # "your token was bad and we dont trust it".
        if not isinstance(e, fxa.errors.TrustError):
            logger.exception("Unexpected verification error")
        # Report an appropriate error code.
        if isinstance(e, ConnectionError):
            request.metrics['token.oauth.connection_error'] = 1
            raise json_error(503, description="Resource is not available")
        raise _unauthorized("invalid-credentials")

    request.metrics['token.oauth.verify_success'] = 1
    request.validated['authorization'] = token

    # OAuth clients should send the scoped-key kid in lieu of X-Client-State.
    # A future enhancement might allow us to learn this from the OAuth
    # verification response rather than requiring a separate header.
    kid = request.headers.get('X-KeyID')
    if kid:
        try:
            # The kid combines a timestamp and a hash of the key material,
            # so we can decode it into equivalent information to what we
            # get out of a BrowserID assertion.
            generation, client_state = kid.split("-", 1)
            generation = int(generation)
            idpClaims = request.validated['authorization']['idpClaims']
            idpClaims['fxa-generation'] = generation
            client_state = browserid.utils.decode_bytes(client_state)
            client_state = client_state.encode('hex')
            if not 1 <= len(client_state) <= 32:
                raise json_error(400, location='header', name='X-Client-State',
                                 description='Invalid client state value')
            # Sanity-check in case the client sent *both* headers.
            # If they don't match, the client is definitely confused.
            if 'X-Client-State' in request.headers:
                if request.headers['X-Client-State'] != client_state:
                    raise _unauthorized("invalid-client-state")
            request.validated['client-state'] = client_state
        except (IndexError, ValueError):
            raise _unauthorized("invalid-credentials")

    id_key = request.registry.settings.get("fxa.metrics_uid_secret_key")
    if id_key is None:
        id_key = 'insecure'
    email = token['email']
    fxa_uid_full = fxa_metrics_hash(email, id_key)
    # "legacy" key used by heka active_counts.lua
    request.metrics['uid'] = fxa_uid_full
    request.metrics['email'] = email

    # "new" keys use shorter values
    fxa_uid = fxa_uid_full[:32]
    request.validated['fxa_uid'] = fxa_uid
    request.metrics['fxa_uid'] = fxa_uid

    # There's currently no notion of a "device id" in OAuth.
    # In future we might be able to use e.g. the refresh token
    # or some derivative of it here.
    device = 'none'
    device_id = fxa_metrics_hash(fxa_uid + device, id_key)[:32]
    request.validated['device_id'] = device_id
    request.metrics['device_id'] = device_id