Merge branch 'bearer-token-url' into 'develop'
Bearer token url See merge request funkwhale/funkwhale!754
This commit is contained in:
commit
a89ebe68b8
|
@ -374,6 +374,7 @@ OAUTH2_PROVIDER = {
|
||||||
"REFRESH_TOKEN_EXPIRE_SECONDS": 3600 * 24 * 15,
|
"REFRESH_TOKEN_EXPIRE_SECONDS": 3600 * 24 * 15,
|
||||||
"AUTHORIZATION_CODE_EXPIRE_SECONDS": 5 * 60,
|
"AUTHORIZATION_CODE_EXPIRE_SECONDS": 5 * 60,
|
||||||
"ACCESS_TOKEN_EXPIRE_SECONDS": 60 * 60 * 10,
|
"ACCESS_TOKEN_EXPIRE_SECONDS": 60 * 60 * 10,
|
||||||
|
"OAUTH2_SERVER_CLASS": "funkwhale_api.users.oauth.server.OAuth2Server",
|
||||||
}
|
}
|
||||||
OAUTH2_PROVIDER_APPLICATION_MODEL = "users.Application"
|
OAUTH2_PROVIDER_APPLICATION_MODEL = "users.Application"
|
||||||
OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = "users.AccessToken"
|
OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = "users.AccessToken"
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
|
@ -77,17 +77,19 @@ import TranslationsMixin from "@/components/mixins/Translations"
|
||||||
export default {
|
export default {
|
||||||
mixins: [TranslationsMixin],
|
mixins: [TranslationsMixin],
|
||||||
props: {
|
props: {
|
||||||
app: {type: Object, required: false}
|
app: {type: Object, required: false},
|
||||||
|
defaults: {type: Object, required: false}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
let app = this.app || {}
|
let app = this.app || {}
|
||||||
|
let defaults = this.defaults || {}
|
||||||
return {
|
return {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
errors: [],
|
errors: [],
|
||||||
fields: {
|
fields: {
|
||||||
name: app.name || '',
|
name: app.name || defaults.name || '',
|
||||||
redirect_uris: app.redirect_uris || 'urn:ietf:wg:oauth:2.0:oob',
|
redirect_uris: app.redirect_uris || defaults.redirect_uris || 'urn:ietf:wg:oauth:2.0:oob',
|
||||||
scopes: app.scopes || 'read'
|
scopes: app.scopes || defaults.scopes || 'read'
|
||||||
},
|
},
|
||||||
scopes: [
|
scopes: [
|
||||||
{id: "profile", icon: 'user'},
|
{id: "profile", icon: 'user'},
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<translate translate-context="Content/Applications/Title">Create a new application</translate>
|
<translate translate-context="Content/Applications/Title">Create a new application</translate>
|
||||||
</h2>
|
</h2>
|
||||||
<application-form
|
<application-form
|
||||||
|
:defaults="defaults"
|
||||||
@created="$router.push({name: 'settings.applications.edit', params: {id: $event.client_id}})" />
|
@created="$router.push({name: 'settings.applications.edit', params: {id: $event.client_id}})" />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
import ApplicationForm from "@/components/auth/ApplicationForm"
|
import ApplicationForm from "@/components/auth/ApplicationForm"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
props: ['name', 'redirect_uris', 'scopes'],
|
||||||
components: {
|
components: {
|
||||||
ApplicationForm
|
ApplicationForm
|
||||||
},
|
},
|
||||||
|
@ -26,6 +28,11 @@ export default {
|
||||||
return {
|
return {
|
||||||
application: null,
|
application: null,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
defaults: {
|
||||||
|
name: this.name,
|
||||||
|
redirect_uris: this.redirect_uris,
|
||||||
|
scopes: this.scopes,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -104,6 +104,11 @@ export default new Router({
|
||||||
{
|
{
|
||||||
path: '/settings/applications/new',
|
path: '/settings/applications/new',
|
||||||
name: 'settings.applications.new',
|
name: 'settings.applications.new',
|
||||||
|
props: (route) => ({
|
||||||
|
scopes: route.query.scopes,
|
||||||
|
name: route.query.name,
|
||||||
|
redirect_uris: route.query.redirect_uris,
|
||||||
|
}),
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "core" */ "@/components/auth/ApplicationNew"),
|
import(/* webpackChunkName: "core" */ "@/components/auth/ApplicationNew"),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue