Documentation update - getting an oauth token from owncloud
I have an application that lives outside of owncloud that needs to get an access token from owncloud via the oauth app.
Doing an authorization request client side to get a code works. But when I pass that to my api to get an access token I get an error "invalid_request"
The request I'm constructing is as follows:
let url = `${url}${service.oauthTokenEndpoint}?grant_type=authorization_code`;
url += `&code=${req.params.code}`;
url += `&redirect_uri=${service.redirectUri}`;
url += `&client_id=${service.clientId}`;
url += `&client_secret=${service.clientSecret}`;
--> url = http://owncloud_server:8080/index.php/apps/oauth2/api/v1/token?grant_type=authorization_code&code=YTk8xFwNU ... M51nABCoTC2uM&redirect_uri=http://localhost:9000/owncloud-callback&client_id=bHj2JMPy ... Db3GUTZ&client_secret=5Bf16MtN ... JE95u3Zm
let response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
According to the RFC : https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3 I might need to add the Authorization header but the docs don't mention it and I don't have the users' name and password anyway.
So, when the request hits the server it fails at https://github.com/owncloud/oauth2/blob/master/lib/Controller/OAuthApiController.php#L122 because the PHP_AUTH_USER and PHP_AUTH_PW var's are not set (I'm guessing these come from the Authorization header being unpacked?).
Anyway, I can't see how this could ever work from outside the owncloud environment or without the users' name and password which shouldn't be needed anyway.
Can you help!
Expected behaviour
The access token should be returned.
Actual behaviour
An 'invalid_request' error is thrown.
Server configuration
- docker container: owncloud/server:10.7
- docker container: Mariadb:10.5
- whatever is in the docker container
- 10.7.0.4
- fresh install
- docker hub
I'm going to leave the original comment in place but i've resolved the issue.
I did need to set the Authorization header using the clientId and clientSecret to generate the basic auth credential.
So now my request looks like:
let url = `${url}${service.oauthTokenEndpoint}?grant_type=authorization_code`;
url += `&code=${req.params.code}`;
url += `&redirect_uri=${service.redirectUri}`;
url += `&client_id=${service.clientId}`;
url += `&client_secret=${service.clientSecret}`;
let auth = Buffer.from(`${service.clientId}:${service.clientSecret}`).toString("base64")
let response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: `Basic ${auth}`,
},
})
Note the extra header with the basic auth.
This isn't clear in the RFC and it's not mentioned in the oauth docs. An example like this in the oauth documentation would have been nice.
I tried this solution but it still needs a human as a user to enter the user/pass on the login page.
in my scenario, I have a worker service that tries to retrieve data from an API that is implemented in OwnCloud. but the Api is not accessible to anonymous users. so my worker service needs to acquire an access token and use that token for authentication and authorization.
something like client_credential flow in Oauth2.
something like
client_credentialflow in Oauth2.
related:
- https://github.com/owncloud/oauth2/issues/354