Dwolla’s new, more secure implementation of OAuth

Hello Dwolla Community,

CORRECTION: OAuth access token expiration begins March 2nd, 2015. The original date mentioned was March 1st.

In our continuous effort to make Dwolla a more secure platform, we are updating our implementation of OAuth to use short-lived access tokens and are deprecating the issuance of “forever-lasting” access tokens which never expire. Beginning March 2nd, 2015, OAuth access tokens will have a lifetime of 1 hour.

Whenever an access token is generated, we’ll also include a refresh token which you can use within 60 days to generate a new access token and refresh token pair. So long as you refresh your authorization every 60 days (or more frequently), applications can still maintain authorization indefinitely without requiring the user to re-authorize the application.

Refresh tokens are long lived: 60 days.
Access tokens are short lived: 1 hour.

By reducing the lifetime of the access token from forever to 1 hour, we significantly narrow the window in which a potential attacker could abuse a compromised OAuth bearer token.

Learn more: we’ve documented the new OAuth implementation here.

Transition Timeline

On October 1st, 2014, we will roll out an initial, non-breaking change. The OAuth /token endpoint will begin to return new parameters in addition to access_token, which is the only parameter it returns today.

On March 2nd, 2015 at 11:00AM EST, newly generated access tokens will have a lifetime of 1 hour, and any existing access tokens will begin to expire.

Any access tokens that are generated between October 1st, 2014 and March 2nd, 2015 will have a special lifetime, in which they will not expire until March 2nd, 2015. This means that any existing applications can continue to operate as they do today without any consequence until March.

Is my application affected by this change?

If you’re only using the Off-Site Gateway, this change will not affect your integration.

Otherwise, if your application uses any of the OAuth endpoints, this is a major breaking change.

There are two common flows behind the usage of our API, which are impacted by this change:

  1. Hardcoded access tokens. Some applications hardcode a single access token and use it to send money from a particular Dwolla account, send money requests, lookup transactions for their account, and so on.
  2. User authorization. Most applications implement OAuth to allow users to grant the application permission to act on their behalf. Typically, the resulting access tokens are stored for future actions, and applications are designed with the expectation that the access token will remain valid indefinitely.

What do I need to do for this change?

Chances are, your existing application has been built with the expectation that access tokens are valid forever. Despite the fact that access tokens will only last 1 hour, your application can continue to maintain authorization indefinitely by periodically refreshing the access token.

Learn how to use the new refresh token with this guide.

We’ve also updated our official API libraries to include new a method to let you easily refresh an access token. Our new dwolla-node library supports refresh out of the box. The dwolla-ruby, dwolla-php, and dwolla-python libraries have been updated, but the changes currently live on the oauth-refresh branch on GitHub. They’ll merged into master and officially updated on October 1st, 2014.

Sandbox Testing

The new OAuth implementation is already available in the sandbox environment (UAT) so you can start testing and developing against it.

As a major breaking change, we understand the work needed to adjust to it is not trivial. If you have any questions or need any help, please don’t hesitate to reach out to us! :smile:

The previous approach of clients being able to store the never-expiring oauth token was definitely better where the need to come back to dwolla to obtain a new OAuth token for every transaction was not necessary. I believe that Dwolla is already generating different OAuth tokens for different clients (applications) for the same end-user. Given this, verifying that the oauth token is associated with the client id/secret coming across on that API call (eg. send) should add another layer of security, where a compromised oauth token alone would be useless to anyone else. This will be on top of the general expectation from client applications (and oauth providers) to communicate over SSL, to keep both oauth and client id/secret combination secure.

1 Like

@sampath,

I definitely agree with you that requiring client id and client secret along with the access token with each API call would be more secure. That is something we’re planning to implement in our next iteration of the API. Moving away from true bearer tokens (which are designed for “any party” to use, not just the application who’s been granted authorization) and ensuring the identity of the party making the call to be the authorized application, we agree, will be more secure.

I want to clarify that under this new OAuth implementation, the user will not need to re-visit the OAuth prompt in order for your application to continue to make transactions on their behalf.

The refresh token process does not require any user intervention, and it’s all done behind the scenes.

Essentially, you can still maintain authorization “forever”, but you just need to keep refreshing your tokens every 60 days.

The one part that’s not clear to me from the documentation: how do we manage the tokens we currently have? For current users, I have an access token, no refresh token. It looks like the only way to get new refresh tokens (without a user reauth) is old refresh tokens. So how do we get our first refresh token for all the users we already have?

Also, another thing about the helper libraries: I currently authorize more or less using the example from the dwolla-ruby library, the relevant part of which is

token = Dwolla::OAuth.get_token(code, redirect_uri)

I.e. get_token gives a string, not a hash or json or anything.
In the new documentation this is now

info = Dwolla::OAuth.get_token(code, redirect_uri)
token = info['access_token']

So it looks to me that the get_token method in the dwolla-ruby library will start returning a hash, meaning if after October 1st I use the current version of the Dwolla library and otherwise don’t change anything, my app will break, unless I’m missing something?

As for your current access tokens, you’ll unfortunately need to have the user re-authorize. We’ve contemplated the idea of exposing an API endpoint which would let you swap an access token for a new access token and refresh token pair, but we decided this would add more complexity to the situation than just having users re-authorize.

For dwolla-ruby, the current version, 2.5.5, on and after Oct. 1 will not break. Dwolla::OAuth.get_token will continue to return a string containing the access token.

On Oct. 1, we’ll release a new version, 2.6.0 that will return a hash instead. If you choose to upgrade to that version, you’re correct – you’ll need to change the way you use get_token.

Do you have any plans to support testing this? Looking at the current rollout plan it doesn’t look like there’s any way to get an access token that will expire after one hour before the 1st March which will make it harder to test that we’re correctly exchanging an old access token/refresh token pair for a new one when necessary.

It would be great to have a testing sandbox where these kind of changes can be rolled out ahead of production to ensure everything is still working correctly (and also to make it possible to test integrations without having to shift real money between real accounts). Do you have any plans to add a developer sandbox?

Does this mean that a normal approach to refreshing tokens would be running a regular batch job that goes about refreshing tokens in order to mimic current functionality of the “never-expiring” token?

I’m also interested in recommendations for testing…will there be any point in time where a refresh token is returned while the “old” auth method still works? (as @harry mentioned, to allow us to make sure things are working/switched over before expiring tokens are required)

edit: after re-reading, it sounds like both methods will be active from Oct 1 to March 15 - allowing us to gradually convert and test properly…thanks guys!

@harry, of course! This change has already been deployed to our Sandbox environment. Newly generated access tokens will have a lifetime of 1 hour, so you can test against that in preparation for March 1st. Learn more about the Sandbox here and check out this in-depth guide on getting started with the sandbox.

@JJHayesIII, you’re correct – you’d want to refresh the tokens regularly (at least every 60 days) with a cron job in order to keep them alive for a long period of time. When making API calls, you should also refresh your tokens to get an access token valid for the next hour.

Let us know if you need any help!

Gordon,

When you say…
“Essentially, you can still maintain authorization “forever”, but you just need to keep refreshing your tokens every 60 days.”

The oAuth token is only valid for 1 hour, so we would need to get a new oAuth every hour if we want a “forever” token.

With every refresh, we will get a new oAuth token along with a new refresh token. Where does the 60 day token come into play?

@gordon Oh wow, when did the sandbox get added? When we developed our integration there was no such thing and we were told that we’d have to test in production.

@Dennis_Thornton what you’re calling an “oAuth token” is actually an access token - you use this to make requests as before. There is also a refresh token which you use to get a pair of new (unexpired) access and refresh tokens. You can refresh your tokens every 60 days to ensure your refresh token is still valid and then whenever you need to make an API call, if your access token has expired, refresh before you make the call to get a valid access token. Of course, if you refresh the access token you also get a new refresh token so this will reset the 60 days as well.

A reasonably easy solution would be to store the last refreshed time with the tokens and run a daily cron job to refresh any tokens where this last refreshed time is more than 59 days ago (or, if you want to be safe against a cron job failing for some reason, more than 50 days ago). If you refresh to get a new token for a user you still set the last refreshed time and then the cron job won’t refresh tokens unnecessarily.

@Dennis_Thornton, @harry is spot on with that explanation.

@harry, we introduced the Sandbox environment to the public in March! We probably should have made a louder announcement about it :slight_smile: .

Hey- Oct. 1 has come and gone and it doesn’t look like a new version of the ruby library has been released. Are there just delays, or has the plan changed, or…?

@Eric_Mayefsky,

I’m actually currently working on packaging and releasing the new Ruby gem! The new version of the library with OAuth Refresh support (and other goodies!) should be released by today EOD :smile:

David

Hey guys–is there a specific time on March 2nd the old tokens will begin to expire? This happens to fall near a relevant moment for an iteration of our product so knowing specifics would be very helpful. Thanks!

Yes. Existing tokens are scheduled to expire at 11:00AM EST on March 2nd 2015. After that time, all access tokens will have a 1 hour lifetime.

Thanks @Eric_Mayefsky, updated the post to reflect this.

@gordon does that also mean that we’ll really have no way of testing proper refresh token behavior before the changeover? I’ve tried forcing the expiration, but I’m guessing that since I don’t have a valid refresh token (and won’t receive one until the 2nd), I’m not able to get anywhere…

@JJHayesIII,

Do you have an application in our sandbox environment? If so, I can set a flag on your application so that new access tokens expire in 1 hour (or less – say 5 minutes, if you’d like). Just let me know what your application is named.

I’ve tried forcing the expiration, but I’m guessing that since I don’t have a valid refresh token (and won’t receive one until the 2nd), I’m not able to get anywhere…

When you get a new access token in production today, you should be getting a refresh token along with it. That refresh token is valid and can be used at any time to refresh the authorization. Keep in mind you can refresh the auth at any time, even before the access token expires.

@gordon yes, I do - I sent you a message with the details last week

My question about simulating expiration was more about transitioning users that have not logged in after the cutover (so therefore cannot have their auth refreshed - they need to re-authorize in order to even get a valid refresh token.

In that vein - are there any plans to offer a tokenInfo or tokenStatus endpoint? Seems I have a need in a few places to check the validity of stored tokens, and trying a request then catching the exception doesn’t seem like a very clean implementation…