Server to Server API calls

Hi,

I’m using DotNetOpenAuth to access the v2 API and I’m unable to
authenticate directly as I would expect it to with server to server
communications using OAuth2.

As an example, using OAuth2 with the new PayPal REST API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new 

Uri(“https://api.sandbox.paypal.com/v1/oauth2/token”);
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my 

secrect");
var token = client.GetClientAccessToken(); // this returns the
Access token as expected.

With the FreeAgent API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new 

Uri(“https://api.freeagent.com/v2/token_endpoint”);
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "My 

secret");
var token = client.GetClientAccessToken(); // I get >>> The
remote server returned an error: (400) Bad Request.

I know I can use the google oauth playground to get the token and refresh
token after I’ve redirected and logged in but this is surely not the final
solution is it? I’d imagine FreeAgent would be working to resolve this
considering they have such a great product. It’s such a shame that the
“hacky” solution above is the “accepted” answer

Thanks for the reply.

In my app I implemented an “in memory” token manager which handles caching
tokens and refreshing them - when my app goes idle and the IIS app pool
recycles, my app re-auth’s on the next request, gets a new token and sticks
it in the “in memory” cache to be used until it expires or my app
recycles… This approach wont work with FreeAgent’s interpretation of
OAuth2 so I guess I will just have to persist the FreeAgent refresh token
like everyone else using your API is having to do (the only “server to
server” OAuth2 API i’m having to do this for)

Shame you’re not considering looking at how companies like PayPal or Google
have implemented OAuth2 as a result of this discussion.

Thanks for the responses anyhow. I guess i’ll just “hack” it together in a
less than ideal way in the short term.On Tuesday, December 10, 2013 1:42:28 PM UTC, Jonathan Barrett wrote:

Hi Mark,

Thanks for taking the time to detail a couple of scenarios for me.

Scenario 1 is essentially what we do at the moment, with the exception
that step 4:

  1. The app can either refresh this token or allow it to expire so that
    the next time the user
    wants to “sync” their data with the app, they are prompted to re-approve
    the request via the
    authorization redirect and it all starts again.

That isn’t quite right. So long as the user has not explicitly revoked the
app’s authorisation, the
app can continue to use its refresh token to retrieve non-expired access
tokens: there’s no
“re-approval” required.

Scenario 2 is also perfectly achievable as a client of the API as-is. Once
you have a refresh token,
your queue can hum away quite happily, refreshing access tokens and
churning through jobs as it
likes.

Your main concern seems to be about the message queue in this example
having to know about access
tokens etc:

  1. The message queue performs its request and disposes of everything,
    not caring about managing
    tokens, refreshes and expiryies etc
  2. A week later another message hits the queue and it starts again…
    no token for just this
    single API is held in the database at the Message Queue’s end to be
    checked and refreshed
    periodically etc via some dodgy scheduled task

I’m not sure I understand this. Are you saying you’d like the queue to be
able to make requests
against the API without being concerned about authentication? Again, given
a refresh token, the
above is simple to achieve without further user intervention. I suspect
I’m missing your concern,
though: sorry about that!

Does that help?

-J

Hi Mark,

Thanks for your feedback.

I totally agree with you when it comes to optimising for developer
happiness. I, too, am a lowly developer (believe it or not!) and OAuth 2
introduces a number of annoying hoops that we have to jump through in order
to make a “simple API request”. As I’m sure you appreciate, though, there
is a constant need to strike a balance between developer happiness and user
experience and security, and I honestly can’t see how any of the
suggestions you have made so far enhance the former without significantly
impeding the latter.

You’re absolutely right when you point out that we don’t support some of
the grant types contained in the OAuth 2 spec proposal. I’m not sure I
agree with you, though, when you use that fact to classify FreeAgent’s
OAuth 2 implementation as “hacky”. If you re-read the Resource Owner
Password Credentials proposal, it’s pretty clear why we’re unlikely to look
to implementing it, and it’s got nothing to do with ignorance of what other
providers are doing. From the proposal:

[Resource Owner Password Credentials] should only be used when there is a

high degree of trust between the resource owner and the client (e.g., the
client is part of the device operating system or a highly privileged
application), and when other authorization grant types are not available
(such as an authorization code).

Neither of those conditions apply to a public API, and certainly not to one
dealing with sensitive financial information. That PayPal has chosen to
implement this is neither here nor there, to be honest: that’s their call
to make, though from reading that spec, I can’t say I understand the
security considerations that have led to them making it.

As ever, we’re very much open to civil and constructive feedback, and your
comments on improving the developer workflow have been noted (and have
generated a few good and interesting ideas among my colleagues). As to your
specific request to implement Resource Owner Password Credentials as a
grant type, I hope I’ve explained why it’s unlikely we’ll be looking to
move on that any time soon, and that it’s got nothing to do with being
inconsiderate of the needs of developers like us :slight_smile:

Thanks again, and please do let us know if you have any other suggestions
or issues that we can look at for you.

Cheers,

-J

Hi Mark,

Thanks for clarifying. You’re right, I hadn’t realised this was a feature
request :slight_smile:

The RFC you link to makes the intent of Resource Owner Password Credentials
pretty clear: it’s for the case where no other grant types are available,
and where there’s a high degree of trust between the resource owner and the
client. In other words, it’s great where you have internal systems that
aren’t exposed to the public, but where there are alternatives available,
they are to be preferred.

There’s also the issue of identifying which “user” in FreeAgent is being
authenticated. It’s entirely possible for a given username/password
combination to be valid against multiple FreeAgent accounts. In the web
app, we use the subdomain to identify intent. When authenticating against
the API using the web flow, we also have a pattern to resolve this so that
we can ensure that the returned token is valid against the intended
account. I’m not sure how we would achieve this given only the username and
password.

Is there a specific use case that I’m missing where your application cannot
use the web flow to authenticate itself against a given user account?

Cheers,

-JOn Mon, Dec 9, 2013 at 2:29 PM, Mark Kneale mark.kneale@gmail.com wrote:

Thanks for the reply Jonathan.

I’m able to use the API using the client credentials flow as per your
documentation just fine… My question is why am I unable to use the
“Resource Owner Password credentials” (
RFC 6749 - The OAuth 2.0 Authorization Framework) as per the PayPalexample in my original post? I’m asking as I don’t think perhaps you’ve
catered for this scenario in the API and it means us lowly developers have
to use different approaches depending on how companies such as yourselves
implement the OAUTH2 specification.

Again, without having to use a Client Authorization Server, the PayPal
REST API works with OAUTH2 as I totally would expect it to:

       var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("https://api.sandbox.

paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my

secrect");
var token = client.GetClientAccessToken(); // this returns
the Access token as expected.

Furthermore, Google Drive API also works in the same way as the PayPal
example above… so what i’m saying is - i’m not looking for support or
having problems that I can’t get around, i’m saying… “The Freeagent
API is missing something”

On Monday, December 9, 2013 11:24:33 AM UTC, Jonathan Barrett wrote:

Hi Mark,

Thanks for getting in touch, and sorry you’re having problems here.

By the looks of things, you’re passing your app’s client ID and secret to
the token endpoint in order to retrieve an access token, but you’re not
specifying the authorisation code for the FreeAgent account against which
your app has been authorised. This authorisation code is a required field,
as specified in the docs:

FreeAgent Developer Dashboard

so you’re getting a Bad Request error since the request is incomplete. If
you hand through the authorisation code for an authorised account, the API
will respond with the correct access token (assuming the user has not
revoked access to your app in the meantime). Retrieving the authorisation
code for an account is detailed here:

FreeAgent Developer Dashboard

and includes the “redirect and log in” step you highlight.

Hope this helps!

-J

On Saturday, 7 December 2013 09:25:26 UTC, Mark Kneale wrote:

Hi,

I’m using DotNetOpenAuth to access the v2 API and I’m unable to
authenticate directly as I would expect it to with server to server
communications using OAuth2.

As an example, using OAuth2 with the new PayPal REST API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("https://api.sandbox.

paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my

secrect");
var token = client.GetClientAccessToken(); // this returns
the Access token as expected.

With the FreeAgent API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("https://api.freeagent.

com/v2/token_endpoint");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "My

secret");
var token = client.GetClientAccessToken(); // I get >>> The
remote server returned an error: (400) Bad Request.

I know I can use the google oauth playground to get the token and
refresh token after I’ve redirected and logged in but this is surely not
the final solution is it? I’d imagine FreeAgent would be working to resolve
this considering they have such a great product. It’s such a shame that the
“hacky” solution above is the “accepted” answer


You received this message because you are subscribed to the Google Groups
“FreeAgent API” group.
To unsubscribe from this group and stop receiving emails from it, send an
email to freeagent_api+unsubscribe@googlegroups.com.
To post to this group, send email to freeagent_api@googlegroups.com.
Visit this group at http://groups.google.com/group/freeagent_api.
For more options, visit https://groups.google.com/groups/opt_out.

Jonathan Barrett, Senior Engineer

FreeAgent: Accounting software, simplified

+44 (0)131 447 0011

Follow us on Twitter: @freeagent https://twitter.com/freeagent

FreeAgent Central Ltd, 40 Torphichen Street, Edinburgh EH3 8JB
Registered in Scotland SC316774

I guess the problem is that my developer account is not tied to my FreeAgent account so this is why the token endpoint wouldn’t know the context of my request and therefore why I’m required to authorise against my own account?

Maybe It would have been better to give every account the ability to generate their own client ID and shared secret within the web app and build the API around this and the developer dashboard for 3rd parties. Context would then be unique to the individual account (unique sub domain containing a unique client id and shared secret) or not in the case of a 3rd party developer only looking to gain delegated access via the aunorization endpoint

Hi Mark,

Thanks for getting in touch, and sorry you’re having problems here.

By the looks of things, you’re passing your app’s client ID and secret to
the token endpoint in order to retrieve an access token, but you’re not
specifying the authorisation code for the FreeAgent account against which
your app has been authorised. This authorisation code is a required field,
as specified in the docs:

so you’re getting a Bad Request error since the request is incomplete. If
you hand through the authorisation code for an authorised account, the API
will respond with the correct access token (assuming the user has not
revoked access to your app in the meantime). Retrieving the authorisation
code for an account is detailed here:

and includes the “redirect and log in” step you highlight.

Hope this helps!

-JOn Saturday, 7 December 2013 09:25:26 UTC, Mark Kneale wrote:

Hi,

I’m using DotNetOpenAuth to access the v2 API and I’m unable to
authenticate directly as I would expect it to with server to server
communications using OAuth2.

As an example, using OAuth2 with the new PayPal REST API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("

https://api.sandbox.paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my 

secrect");
var token = client.GetClientAccessToken(); // this returns the
Access token as expected.

With the FreeAgent API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("

https://api.freeagent.com/v2/token_endpoint");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "My 

secret");
var token = client.GetClientAccessToken(); // I get >>> The
remote server returned an error: (400) Bad Request.

I know I can use the google oauth playground to get the token and refresh
token after I’ve redirected and logged in but this is surely not the final
solution is it? I’d imagine FreeAgent would be working to resolve this
considering they have such a great product. It’s such a shame that the
“hacky” solution above is the “accepted” answer

Hi Mark,

Thanks for taking the time to detail a couple of scenarios for me.

Scenario 1 is essentially what we do at the moment, with the exception that
step 4:

  1. The app can either refresh this token or allow it to expire so that
    the next time the user
    wants to “sync” their data with the app, they are prompted to re-approve
    the request via the
    authorization redirect and it all starts again.

That isn’t quite right. So long as the user has not explicitly revoked the
app’s authorisation, the
app can continue to use its refresh token to retrieve non-expired access
tokens: there’s no
“re-approval” required.

Scenario 2 is also perfectly achievable as a client of the API as-is. Once
you have a refresh token,
your queue can hum away quite happily, refreshing access tokens and
churning through jobs as it
likes.

Your main concern seems to be about the message queue in this example
having to know about access
tokens etc:

  1. The message queue performs its request and disposes of everything, not
    caring about managing
    tokens, refreshes and expiryies etc
  2. A week later another message hits the queue and it starts again… no
    token for just this
    single API is held in the database at the Message Queue’s end to be
    checked and refreshed
    periodically etc via some dodgy scheduled task

I’m not sure I understand this. Are you saying you’d like the queue to be
able to make requests
against the API without being concerned about authentication? Again, given
a refresh token, the
above is simple to achieve without further user intervention. I suspect I’m
missing your concern,
though: sorry about that!

Does that help?

-J

Thanks for the reply Jonathan.

I’m able to use the API using the client credentials flow as per your
documentation just fine… My question is why am I unable to use the
“Resource Owner Password credentials” (
RFC 6749 - The OAuth 2.0 Authorization Framework) as per the PayPalexample in my original post? I’m asking as I don’t think perhaps you’ve
catered for this scenario in the API and it means us lowly developers have
to use different approaches depending on how companies such as yourselves
implement the OAUTH2 specification.

Again, without having to use a Client Authorization Server, the PayPal
REST API works with OAUTH2 as I totally would expect it to:

       var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("

https://api.sandbox.paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my 

secrect");
var token = client.GetClientAccessToken(); // this returns the
Access token as expected.

Furthermore, Google Drive API also works in the same way as the PayPal
example above… so what i’m saying is - i’m not looking for support or
having problems that I can’t get around, i’m saying… *“The Freeagent API
is missing something”*On Monday, December 9, 2013 11:24:33 AM UTC, Jonathan Barrett wrote:

Hi Mark,

Thanks for getting in touch, and sorry you’re having problems here.

By the looks of things, you’re passing your app’s client ID and secret to
the token endpoint in order to retrieve an access token, but you’re not
specifying the authorisation code for the FreeAgent account against which
your app has been authorised. This authorisation code is a required field,
as specified in the docs:

FreeAgent Developer Dashboard

so you’re getting a Bad Request error since the request is incomplete. If
you hand through the authorisation code for an authorised account, the API
will respond with the correct access token (assuming the user has not
revoked access to your app in the meantime). Retrieving the authorisation
code for an account is detailed here:

FreeAgent Developer Dashboard

and includes the “redirect and log in” step you highlight.

Hope this helps!

-J

On Saturday, 7 December 2013 09:25:26 UTC, Mark Kneale wrote:

Hi,

I’m using DotNetOpenAuth to access the v2 API and I’m unable to
authenticate directly as I would expect it to with server to server
communications using OAuth2.

As an example, using OAuth2 with the new PayPal REST API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("

https://api.sandbox.paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my 

secrect");
var token = client.GetClientAccessToken(); // this returns
the Access token as expected.

With the FreeAgent API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("

https://api.freeagent.com/v2/token_endpoint");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "My 

secret");
var token = client.GetClientAccessToken(); // I get >>> The
remote server returned an error: (400) Bad Request.

I know I can use the google oauth playground to get the token and refresh
token after I’ve redirected and logged in but this is surely not the final
solution is it? I’d imagine FreeAgent would be working to resolve this
considering they have such a great product. It’s such a shame that the
“hacky” solution above is the “accepted” answer

Thanks for the reply Jonathan.

The way I would imagine it should work:

Scenario 1: An app wants it’s users (resource owners) to authorize the app
(client) to access their FreeAgent data

  1. They approve the apps request on the FreeAgent authorization page and an
    authorization code is returned via the redirect to the app
  2. The app exchanges the authorization code for a token/refresh
    (Authorization State)
  3. The app accesses the users data within the scope they have approved and
    in the context of the access token (this is what ties the request to the
    users account - not the authorization code or the apps client identifier or
    the shared secret)
  4. The app can either refresh this token or allow it to expire so that the
    next time the user wants to “sync” their data with the app, they are
    prompted to re-approve the request via the authorization redirect and it
    all starts again.

Scenario 2: A company who uses FreeAgent wants their corporate website to
send API calls via a message queue to create contacts and generate invoices
in their own FreeAgent account (They are both the resource owner and the
client)

  1. Data is sent to the message queue at any random period - could be once
    in a week or nothing for a few weeks
  2. The message queue listens and fires off an API call using the client
    identifier and shared secret (just like my PayPal example)
  3. The FreeAgent API directly returns the token/refresh (Authorization
    state) - This is not delegated access and should not require the resource
    owner (the company) to visit a web page and approve themselves to access
    their own data
  4. The message queue performs it’s request and disposes of everything, not
    caring about managing tokens, refreshes and expiry’s etc
  5. A week later another message hits the queue and it starts again… no
    token for just this single API is held in the database at the Message
    Queue’s end to be checked and refreshed periodically etc via some dodgy
    scheduled task

For the record. I think FreeAgent and the direction of the API is
brilliant. Keep up the great work guys and hope I could be of some
assistance.

Cheers,
MarkOn Monday, December 9, 2013 4:37:40 PM UTC, Jonathan Barrett wrote:

Hi Mark,

Thanks for clarifying. You’re right, I hadn’t realised this was a feature
request :slight_smile:

The RFC you link to makes the intent of Resource Owner Password
Credentials pretty clear: it’s for the case where no other grant types are
available, and where there’s a high degree of trust between the resource
owner and the client. In other words, it’s great where you have internal
systems that aren’t exposed to the public, but where there are alternatives
available, they are to be preferred.

There’s also the issue of identifying which “user” in FreeAgent is being
authenticated. It’s entirely possible for a given username/password
combination to be valid against multiple FreeAgent accounts. In the web
app, we use the subdomain to identify intent. When authenticating against
the API using the web flow, we also have a pattern to resolve this so that
we can ensure that the returned token is valid against the intended
account. I’m not sure how we would achieve this given only the username and
password.

Is there a specific use case that I’m missing where your application
cannot use the web flow to authenticate itself against a given user account?

Cheers,

-J

On Mon, Dec 9, 2013 at 2:29 PM, Mark Kneale <mark....@gmail.com<javascript:> wrote:

Thanks for the reply Jonathan.

I’m able to use the API using the client credentials flow as per your
documentation just fine… My question is why am I unable to use the
“Resource Owner Password credentials” (
RFC 6749 - The OAuth 2.0 Authorization Framework) as per the PayPalexample in my original post? I’m asking as I don’t think perhaps you’ve
catered for this scenario in the API and it means us lowly developers have
to use different approaches depending on how companies such as yourselves
implement the OAUTH2 specification.

Again, without having to use a Client Authorization Server, the PayPal
REST API works with OAUTH2 as I totally would expect it to:

       var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("https://api.sandbox.

paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", "my 

secrect");
var token = client.GetClientAccessToken(); // this returns
the Access token as expected.

Furthermore, Google Drive API also works in the same way as the PayPal
example above… so what i’m saying is - i’m not looking for support or
having problems that I can’t get around, i’m saying… “The Freeagent
API is missing something”

On Monday, December 9, 2013 11:24:33 AM UTC, Jonathan Barrett wrote:

Hi Mark,

Thanks for getting in touch, and sorry you’re having problems here.

By the looks of things, you’re passing your app’s client ID and secret
to the token endpoint in order to retrieve an access token, but you’re not
specifying the authorisation code for the FreeAgent account against which
your app has been authorised. This authorisation code is a required field,
as specified in the docs:

FreeAgent Developer Dashboard

so you’re getting a Bad Request error since the request is incomplete.
If you hand through the authorisation code for an authorised account, the
API will respond with the correct access token (assuming the user has not
revoked access to your app in the meantime). Retrieving the authorisation
code for an account is detailed here:

FreeAgent Developer Dashboard

and includes the “redirect and log in” step you highlight.

Hope this helps!

-J

On Saturday, 7 December 2013 09:25:26 UTC, Mark Kneale wrote:

Hi,

I’m using DotNetOpenAuth to access the v2 API and I’m unable to
authenticate directly as I would expect it to with server to server
communications using OAuth2.

As an example, using OAuth2 with the new PayPal REST API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("https://api.sandbox.

paypal.com/v1/oauth2/token");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", 

“my secrect”);
var token = client.GetClientAccessToken(); // this returns
the Access token as expected.

With the FreeAgent API:

        var server = new AuthorizationServerDescription();
        server.TokenEndpoint = new Uri("https://api.freeagent.

com/v2/token_endpoint");
server.ProtocolVersion = ProtocolVersion.V20;

        var client = new UserAgentClient(server, "my client ID", 

“My secret”);
var token = client.GetClientAccessToken(); // I get >>> The
remote server returned an error: (400) Bad Request.

I know I can use the google oauth playground to get the token and
refresh token after I’ve redirected and logged in but this is surely not
the final solution is it? I’d imagine FreeAgent would be working to resolve
this considering they have such a great product. It’s such a shame that the
“hacky” solution above is the “accepted” answer


You received this message because you are subscribed to the Google Groups
“FreeAgent API” group.
To unsubscribe from this group and stop receiving emails from it, send an
email to freeagent_ap...@googlegroups.com <javascript:>.
To post to this group, send email to freeag...@googlegroups.com<javascript:>
.
Visit this group at http://groups.google.com/group/freeagent_api.
For more options, visit https://groups.google.com/groups/opt_out.

Jonathan Barrett, Senior Engineer

FreeAgent: Accounting software, simplified
www.freeagent.com

+44 (0)131 447 0011

Follow us on Twitter: @freeagent https://twitter.com/freeagent

FreeAgent Central Ltd, 40 Torphichen Street, Edinburgh EH3 8JB
Registered in Scotland SC316774