This spits out a url which I can use to approve the app for my account, however after that I get bounced to the google oauth playground. There’s a button that says “exchange authorisation code for tokens” but when I click on it I get “Malformed auth code”.
I’d rather not use google services in general. Do you have any example code for authentication with oauth2?
Ok so I’ve made a bit of progress but now when I pass the authorisation code to the /v2/token_endpoint endpoint I just get a 401 basic authorization error. I’m pretty sure the authorisation credentials are correct, I’ve even tried passing them with the curl -u parameter.
Hello! So here is a very simple Ruby app using OAuth2.
require 'oauth2'
client_id = "OAuth identifier from your app set up"
client_secret = "OAuth secret from your app set up"
client = OAuth2::Client.new(
client_id,
client_secret,
authorize_url: "/v2/approve_app",
token_url: "/v2/token_endpoint",
site: 'https://api.sandbox.freeagent.com',
)
# redirect_uri must match one of those listed when you created your app
auth_url = client.auth_code.authorize_url(redirect_uri: "https://developers.google.com/oauthplayground")
# Once you've built the auth url, you will need to follow it and approve the app. Once you've done that you'll get
# redirected and you'll get a token.
# In the case of this example it is using Google so the page it takes me to will be the same one in our documentation. In
# the slider on the left under "Step 2" you'll have an Authorization code there. You use that in the `auth_code` field below.
# If you don't want to use Google, you need to have some TLS secured URL you can redirect to (see this for more information -
# https://aaronparecki.com/oauth-2-simplified/). You could do this for local testing by, say, creating a simple app running
# SSL with your own self-signed certs that just spits out the code from the URL params.
auth_code = "code from the above authorize URL redirect"
token = client.auth_code.get_token(auth_code, redirect_uri: "https://developers.google.com/oauthplayground")
response = token.get("https://api.sandbox.freeagent.com/v2/company")
# If you are making the request as part of a Practice, you'll need to add the X-Subdomain header specifying subdomain of
# the Practice's company you're making the request for.
# response = token.get("https://api.sandbox.freeagent.com/v2/company", headers: { "X-Subdomain": "companysubdomain" }
require 'json'
puts JSON.parse(response.body)
Now, as to your latest update. You can definitely do it via cUrl. You can use basic auth like you did or user/pass in the query string. I see you’ve opened a ticket with Support already. If, as part of that ticket, you can give them your Client ID, that can help us with debugging. (If you post here when you’ve done that, I can follow up with Support).
Hi, thanks for the response. What you’ve pasted seems to be exactly what I was doing, I only switched to a raw curl request for the token exchange in order to rule out some kind of issue with the ruby gem being the cause and also to see exactly what the http response was. I’ve given support my client id so hopefully they’ll get back to me soon. The response to the curl command seemed to suggest the basic authentication was failing. I was not using the sandbox but the live endpoint, is there some special activation that needs to occur before an application can use that? I didn’t see anything in the freeagent oauth documentation about it but I’ve encountered this with other services before.
So this is the code I was using with the ruby gem, I think it’s essentially the same as yours.
require 'oauth2'
require 'base64'
client_id = ""
client_secret = ""
client = OAuth2::Client.new(
client_id,
client_secret,
:authorize_url => "/v2/approve_app",
:token_url => "/v2/token_endpoint",
:site => 'https://api.freeagent.com',
)
puts client.auth_code.authorize_url
# at this point browse to the url and copy/paste the code from the url
print "code: "
code = $stdin.readline.chomp
token = client.auth_code.get_token(
code,
:redirect_uri => 'https://a.rkw.io'
)
p token
result:
/var/lib/gems/2.3.0/gems/oauth2-1.4.0/lib/oauth2/client.rb:119:in `request': invalid_grant: (OAuth2::Error)
{"error":"invalid_grant"}
from /var/lib/gems/2.3.0/gems/oauth2-1.4.0/lib/oauth2/client.rb:146:in `get_token'
from /var/lib/gems/2.3.0/gems/oauth2-1.4.0/lib/oauth2/strategy/auth_code.rb:30:in `get_token'
from ./test.rb:27:in `<main>'
Thanks for the code, Mark. No, there’s no activation that needs doing for a non-Practice app. The two environments (sandbox and production) are completely separate.
If I had to guess, I’d say the id and secret you’re using don’t match what we have here. If you don’t mind, can you please regenerate your client tokens (via the https://dev.freeagent.com/apps site) and try again.
I’ve already tried destroying and re-creating the app to no avail, also I can see that the client id and secret on the application page are correct and match what’s in the code.
I’ve just regenerated them and the result is the same.
Are there not logs you can inspect to determine the reason why the requests are failing? That would seem like a much quicker path to resolving this than guessing.
For anyone looking at this in the future, the problem was due to using a redirect_uri in get_token and not authorize_url. If you use it in one, you need to use it in the other.
Thanks for your help Pat. Is this a generic oauth2 requirement or is it a feature of your implementation? Is there any scope for making the error response a bit more intuitive? I was thinking perhaps inject a header into the 401 response to indicate why it failed, but you can’t really say it’s a uri mismatch because the uri was essentially the same for both requests, it was just implicit in one and explicit in the other. I guess exposing the details of that could introduce security issues.