docs: async def login(self, client_name, request, redirect_uri=None, **params):
          """Process login with OAuth.
  
          :param client_name: A name one of configured clients
          :param request: Web request
          :param redirect_uri: An URI for authorization redirect
          """
          client = self.client(client_name, logger=self.app.logger)
  
          redirect_uri = redirect_uri or self.cfg.redirect_uri or '%s://%s%s' % (
              request.scheme, request.host, request.path)
          session = await self.app.ps.session(request)
  
          if isinstance(client, OAuth1Client):
              oauth_verifier = request.query.get('oauth_verifier')
              if not oauth_verifier:
  
                  # Get request credentials
                  token, secret = await client.get_request_token(
                      oauth_callback=redirect_uri)
  
                  # Save the credentials in current user session
                  session['oauth_token'] = token
                  session['oauth_token_secret'] = secret
  
                  url = client.get_authorize_url()
                  raise muffin.HTTPFound(url)
  
              # Check request_token
              oauth_token = request.query.get('oauth_token')
              if session['oauth_token'] != oauth_token:
                  raise muffin.HTTPForbidden(reason='Invalid token.')
  
              client.oauth_token = oauth_token
              client.oauth_token_secret = session.get('oauth_token_secret')
  
              # Get access tokens
              return client, await client.get_access_token(oauth_verifier)
  
          if isinstance(client, OAuth2Client):
              code = request.query.get('code')
              if not code:
  
                  # Authorize an user
                  state = sha1(str(random()).encode('ascii')).hexdigest()
                  session['oauth_secret'] = state
                  url = client.get_authorize_url(
                      redirect_uri=redirect_uri, state=state, **params)
                  raise muffin.HTTPFound(url)
  
              # Check state
              state = request.query.get('state')
              oauth_secret = session.pop('oauth_secret', '')
              if oauth_secret != state:
                  raise muffin.HTTPForbidden(reason='Invalid token "%s".' % oauth_secret)
  
              # Get access token
              return client, await client.get_access_token(code, redirect_uri=redirect_uri)
  
          return client