Skip to content
Snippets Groups Projects
Commit 708e9dd1 authored by EorlBruder's avatar EorlBruder
Browse files

Added OAuth login-method

- Added separate method for the login. This method takes the
  client-id and client-secret as params.
- Added method to refresh the oauth-token
parent 309aa8bb
No related branches found
No related tags found
No related merge requests found
import urllib.parse
import webbrowser
import aiohttp import aiohttp
from . import exceptions from . import exceptions
...@@ -56,6 +59,40 @@ async def get_jwt_token(session, url, username, password): ...@@ -56,6 +59,40 @@ async def get_jwt_token(session, url, username, password):
return (await response.json())["token"] return (await response.json())["token"]
async def get_oauth_token(session, url, client_id, client_secret):
args = {"response_type": "code", "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", "client_id": client_id,
"client_secret": client_secret, "scope": "read write"}
browser_url = f"{url}authorize?{urllib.parse.urlencode(args)}"
webbrowser.open(browser_url)
code = input("Enter the code from funkwhale")
api_url = f"{url}api/v1/oauth/token/"
response = await session.post(
api_url, data={"client_id": client_id, "client_secret": client_secret,
"grant_type": "authorization_code", "code": code}
)
return await extract_tokens(response)
async def refresh_oauth_token(session, url, client_id, client_secret, refresh_token):
api_url = f"{url}api/v1/oauth/token/"
response = await session.post(
api_url, data={"client_id": client_id, "client_secret": client_secret,
"grant_type": "refresh_token", "refresh_token": refresh_token}
)
return await extract_tokens(response)
async def extract_tokens(response):
if response.status == 400:
raise exceptions.AuthenticationError(
"Unable to log in with provided credentials"
)
response_json = await response.json()
access_token = response_json["access_token"]
refresh_token = response_json["refresh_token"]
return access_token, refresh_token
class API(object): class API(object):
def __init__(self, base_url, token): def __init__(self, base_url, token):
self.base_url = base_url self.base_url = base_url
......
...@@ -95,9 +95,62 @@ async def login(ctx, username, password): ...@@ -95,9 +95,62 @@ async def login(ctx, username, password):
click.echo("Login successfull!") click.echo("Login successfull!")
@base.cli.command()
@click.option("-i", "--client-id", envvar="FUNKWHALE_CLIENT_ID", prompt=True)
@click.option(
"-s", "--client-secret", envvar="FUNKWHALE_CLIENT_SECRET", prompt=True, hide_input=True
)
@click.pass_context
@base.async_command
async def login_oauth(ctx, client_id, client_secret):
async with api.get_session() as session:
access_token, refresh_token = await api.get_oauth_token(
session, ctx.obj["SERVER_URL"], client_id=client_id, client_secret=client_secret
)
process_access_tokens(ctx, access_token, refresh_token)
click.echo("Login successful!")
@base.cli.command()
@click.option("-i", "--client-id", envvar="FUNKWHALE_CLIENT_ID", prompt=True)
@click.option(
"-s", "--client-secret", envvar="FUNKWHALE_CLIENT_SECRET", prompt=True, hide_input=True
)
@click.pass_context
@base.async_command
async def refresh_auth(ctx, client_id, client_secret):
refresh_token = keyring.get_password(ctx.obj["SERVER_URL"], "refresh")
async with api.get_session() as session:
access_token, refresh_token = await api.refresh_oauth_token(
session, ctx.obj["SERVER_URL"], client_id=client_id, client_secret=client_secret,
refresh_token=refresh_token
)
process_access_tokens(ctx, access_token, refresh_token)
click.echo("Login successful, tokens are refreshed!")
def process_access_tokens(ctx, access_token, refresh_token):
try:
keyring.set_password(ctx.obj["SERVER_URL"], "_", access_token)
keyring.set_password(ctx.obj["SERVER_URL"], "refresh", refresh_token)
except ValueError as e:
raise click.ClickException(
"Error while saving password to keyring: {}.".format(
e.args[0]
)
)
except Exception as e:
raise click.ClickException(
"Error while saving password to keyring: {}".format(e.args[0])
)
@base.cli.command() @base.cli.command()
@click.pass_context @click.pass_context
@base.async_command @base.async_command
async def logout(ctx): async def logout(ctx):
keyring.delete_password(ctx.obj["SERVER_URL"], "_") keyring.delete_password(ctx.obj["SERVER_URL"], "_")
click.echo("Logout successfull!") keyring.delete_password(ctx.obj["SERVER_URL"], "refresh")
click.echo("Logout successful!")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment