diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index 3000feddba0ee07e93fc4d54caac0b5d8fd66ee1..bf357e17c1e38e3d3a166fe55845811eb3e0d776 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -374,6 +374,7 @@ OAUTH2_PROVIDER = {
     "REFRESH_TOKEN_EXPIRE_SECONDS": 3600 * 24 * 15,
     "AUTHORIZATION_CODE_EXPIRE_SECONDS": 5 * 60,
     "ACCESS_TOKEN_EXPIRE_SECONDS": 60 * 60 * 10,
+    "OAUTH2_SERVER_CLASS": "funkwhale_api.users.oauth.server.OAuth2Server",
 }
 OAUTH2_PROVIDER_APPLICATION_MODEL = "users.Application"
 OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = "users.AccessToken"
diff --git a/api/funkwhale_api/users/oauth/server.py b/api/funkwhale_api/users/oauth/server.py
new file mode 100644
index 0000000000000000000000000000000000000000..f62ebf48a93c438e1f762dc95c2b2d0e85013111
--- /dev/null
+++ b/api/funkwhale_api/users/oauth/server.py
@@ -0,0 +1,25 @@
+import urllib.parse
+import oauthlib.oauth2
+
+
+class OAuth2Server(oauthlib.oauth2.Server):
+    def verify_request(self, uri, *args, **kwargs):
+        valid, request = super().verify_request(uri, *args, **kwargs)
+        if valid:
+            return valid, request
+
+        # maybe the token was given in the querystring?
+        query = urllib.parse.urlparse(request.uri).query
+        token = None
+        if query:
+            parsed_qs = urllib.parse.parse_qs(query)
+            token = parsed_qs.get("token", [])
+            if len(token) > 0:
+                token = token[0]
+
+        if token:
+            valid = self.request_validator.validate_bearer_token(
+                token, request.scopes, request
+            )
+
+        return valid, request
diff --git a/api/tests/test_auth.py b/api/tests/test_auth.py
new file mode 100644
index 0000000000000000000000000000000000000000..653110f0944e0b08e13bf40f97460de4d47a83da
--- /dev/null
+++ b/api/tests/test_auth.py
@@ -0,0 +1,36 @@
+from django.urls import reverse
+from rest_framework_jwt.settings import api_settings
+
+jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
+jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
+
+
+def test_can_authenticate_using_jwt_token_param_in_url(factories, preferences, client):
+    user = factories["users.User"]()
+    preferences["common__api_authentication_required"] = True
+    url = reverse("api:v1:tracks-list")
+    response = client.get(url)
+
+    assert response.status_code == 401
+
+    payload = jwt_payload_handler(user)
+    token = jwt_encode_handler(payload)
+    response = client.get(url, data={"jwt": token})
+    assert response.status_code == 200
+
+
+def test_can_authenticate_using_oauth_token_param_in_url(
+    factories, preferences, client, mocker
+):
+    mocker.patch(
+        "funkwhale_api.users.oauth.permissions.should_allow", return_value=True
+    )
+    token = factories["users.AccessToken"]()
+    preferences["common__api_authentication_required"] = True
+    url = reverse("api:v1:tracks-list")
+    response = client.get(url)
+
+    assert response.status_code == 401
+
+    response = client.get(url, data={"token": token.token})
+    assert response.status_code == 200
diff --git a/api/tests/test_jwt_querystring.py b/api/tests/test_jwt_querystring.py
deleted file mode 100644
index 18a673fb480d71fdea41dc60557dfd56b6c34aaa..0000000000000000000000000000000000000000
--- a/api/tests/test_jwt_querystring.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.urls import reverse
-from rest_framework_jwt.settings import api_settings
-
-jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
-jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
-
-
-def test_can_authenticate_using_token_param_in_url(factories, preferences, client):
-    user = factories["users.User"]()
-    preferences["common__api_authentication_required"] = True
-    url = reverse("api:v1:tracks-list")
-    response = client.get(url)
-
-    assert response.status_code == 401
-
-    payload = jwt_payload_handler(user)
-    token = jwt_encode_handler(payload)
-    response = client.get(url, data={"jwt": token})
-    assert response.status_code == 200
diff --git a/front/src/components/auth/ApplicationForm.vue b/front/src/components/auth/ApplicationForm.vue
index 5bd7d3b504ae623058a2da39b7f01e0a85206bed..c2eefbfdfb705643aad0bf728e7f8764a7d3a6af 100644
--- a/front/src/components/auth/ApplicationForm.vue
+++ b/front/src/components/auth/ApplicationForm.vue
@@ -77,17 +77,19 @@ import TranslationsMixin from "@/components/mixins/Translations"
 export default {
   mixins: [TranslationsMixin],
   props: {
-    app: {type: Object, required: false}
+    app: {type: Object, required: false},
+    defaults: {type: Object, required: false}
   },
   data() {
     let app = this.app || {}
+    let defaults = this.defaults || {}
     return {
       isLoading: false,
       errors: [],
       fields: {
-        name: app.name || '',
-        redirect_uris: app.redirect_uris || 'urn:ietf:wg:oauth:2.0:oob',
-        scopes: app.scopes || 'read'
+        name: app.name || defaults.name || '',
+        redirect_uris: app.redirect_uris || defaults.redirect_uris || 'urn:ietf:wg:oauth:2.0:oob',
+        scopes: app.scopes || defaults.scopes || 'read'
       },
       scopes: [
         {id: "profile", icon: 'user'},
diff --git a/front/src/components/auth/ApplicationNew.vue b/front/src/components/auth/ApplicationNew.vue
index 8bb36826ce9bef3931f0091b50e5213cbe108124..ba1a575fe79a95ae72d4c6f4611986bbc9efe9cb 100644
--- a/front/src/components/auth/ApplicationNew.vue
+++ b/front/src/components/auth/ApplicationNew.vue
@@ -9,6 +9,7 @@
           <translate translate-context="Content/Applications/Title">Create a new application</translate>
         </h2>
         <application-form
+          :defaults="defaults"
           @created="$router.push({name: 'settings.applications.edit', params: {id: $event.client_id}})" />
       </section>
     </div>
@@ -19,6 +20,7 @@
 import ApplicationForm from "@/components/auth/ApplicationForm"
 
 export default {
+  props: ['name', 'redirect_uris', 'scopes'],
   components: {
     ApplicationForm
   },
@@ -26,6 +28,11 @@ export default {
     return {
       application: null,
       isLoading: false,
+      defaults: {
+        name: this.name,
+        redirect_uris: this.redirect_uris,
+        scopes: this.scopes,
+      }
     }
   },
   computed: {
diff --git a/front/src/router/index.js b/front/src/router/index.js
index 7b97cbe513edde232df3756418fd783225a04db1..182cf61b0714f6f2feecc529526b314d475ccab3 100644
--- a/front/src/router/index.js
+++ b/front/src/router/index.js
@@ -104,6 +104,11 @@ export default new Router({
     {
       path: '/settings/applications/new',
       name: 'settings.applications.new',
+      props: (route) => ({
+        scopes: route.query.scopes,
+        name: route.query.name,
+        redirect_uris: route.query.redirect_uris,
+      }),
       component: () =>
         import(/* webpackChunkName: "core" */ "@/components/auth/ApplicationNew"),
     },