postmanlabs / postman-app-support

Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.
https://www.postman.com
5.81k stars 839 forks source link

Add option to refresh OAuth 2.0 tokens [Available from v10.6] #2452

Closed seppestas closed 1 year ago

seppestas commented 7 years ago

It would be very handy to have the Postman OAuth 2.0 authentication helper parse the expires_in field of OAuth 2.0 access tokens if it is available and provide some sort of flag to see whether a token has expired.

It would be even more useful to have the option to refresh a token when the refresh_token of the access token is available. This would prevent a whole bunch tokens with the same attributes from piling up in the "Existing Tokens" list when using an API that uses token expiry.

These 2 features could be combined into a super useful message that shows up when a token expired and says something like "This token has expired. Refresh token?".

vegetableman commented 7 years ago

@seppestas Thanks for reporting this issue 👍 . Will keep you updated on this thread,

janslow commented 7 years ago

This would also be useful for us, as our access tokens have to be refreshed every 5 minutes.

riquack commented 7 years ago

Would be nice just to have a Refresh Token button right next to the Use Token button 😄

ghost commented 7 years ago

Yea, the workflow for getting tokens needs to improve. Here is what I have to do frequently.

  1. Scroll
  2. Click Authorization
  3. Select auth type. (This selection is not saved along with the query.)
  4. Click get "New Access Token"
  5. Click on the new token item in the list, because it is not selected automatically.
  6. Click use token button.

If I open another saved request, I have to repeat most of the steps above. Postman should be able to go out and automatically fetch new tokens if they are expired. It should also be linked to an environment. So there can be different auth settings for different environments.

Thanks

seppestas commented 7 years ago

I'm personally not a fan of the idea of Postman automatically fetching new tokens. A refresh token button gives a lot more control and options to the user like e.g refreshing the token before it expires.

For my use of Postman having the "auth settings" saved per collection makes a lot of sense. These settings can refer to things like domain names set in the environment settings. It would be nice to able to automatically use the same access token for request in a collection in the same environment as well though.

rationull commented 7 years ago

+1 on a "refresh" button and on allowing per-collection "current token" and auth settings.

ankitbko commented 7 years ago

+1 Bump. Almost going to be a year, any plans for this?

asgeirn commented 6 years ago

Since I'm working with an internal IDP with 1 hour expiration, I've set up an OAuth 2.0 request as the first in the collection to get a valid access token.

OAuth 2.0.postman_collection.json.txt

trev commented 6 years ago

@asgeirn That works fine for the Resource owner credentials grant type but not the Authorization code grant.

simonhamp commented 6 years ago

I routinely have to test 3 different grant types with an increasing number of scopes, each on 3 separate environments (at least) - local, staging and production. Our tokens last for 48 hours, but lacking the ability to refresh tokens is the cause of a lot of personal frustration right now:

  1. It causes the current Postman workflow to be very stop-start as I have to go into the Auth panel, request a new token etc etc
  2. It kind of breaks the UI too, as I end up creating multiple tokens and I have to keep adding and deleting tokens manually which is a pain.
  3. Because there's no tracking of expiry, Postman assumes that the current token can just be attempted... it can be smarter than this 😉
  4. There are some annoying little issues with the UI (e.g. multiple overlays) which make this whole process a bit more yucky at the moment.

Postman is definitely making my life a lot easier right now, but these little refinements would go a really long way and make this aspect of testing super powerful.

An alternative/additional useful thing would be at least to be able to create authorization templates so I can more easily create the kind of tokens I usually have to create. I can't really achieve what I want with environment variables. For example, I routinely have to create tokens with the following settings:

grant_type: client_credentials
scopes: scope-one
---
grant_type: authorization_code
scopes: scope-two
---
grant_type: password
scopes: scope-three

The current UI only remembers the last grant type, name and scopes (my other variables are environment variables). This is not so helpful though as I end up having to type the same things over and over: change the title, change the grant type, change the scopes.

It would be awesome if I could choose a template and create a new token from that so I could remove a few steps every time a token expires.

zlanich commented 6 years ago

Any update on this? My tokens have a 10min TTL, so refreshing access tokens every 10min definitely gets old.

egilegil commented 6 years ago

This is indeed an issue in our project as well where we have 5 min TTL on our tokens, but refresh tokens have a more or less infinite life span. So I guess this is +1 from me as well :-)

aonurdemir commented 6 years ago

I need refresh button badly since I am testing with multiple accounts using password grant. When one of them is expired and it is not the last one created, I have to enter username and password again. Considering low TTLs, this is getting frustrating.

kasvith commented 6 years ago

@aonurdemir we can use also pre request on your requests and set environment variable like this on every request you want.

You also can apply pre request to a Folder also

image

ghost commented 6 years ago

Better then a refresh token button would be if it just refreshed the token by itself.

rfrew commented 6 years ago

We did the same thing as @kasvith The only other added thing we did is add in a {token_time} Key so we did not go get a new token every time we made a request. @simonhamp that might help you with your timeout situation. I go crazy with variables because I have different environments all of the place that I use the same call for.

The code

// pm.globals.get()

if(pm.environment.get("token_time") <= Date.now()) {
    var oauth_auth = 'Basic ' + btoa(pm.environment.get("API-Key") + ':' + pm.environment.get("client_secret"));
    pm.sendRequest({
        url: pm.environment.get("oauth_url"),
        method: 'POST',
        header: {
            'Authorization': oauth_auth,
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        },
        body: {
            mode: 'raw',
            raw: 'grant_type=client_credentials'
        }
    }, function (err, res) {
        pm.environment.set("auth_secret_gen", res.json().access_token);
        pm.environment.set("token_time", Date.now() + 60*60*1000); //60*60*1000 = 1hr in milliseconds
    });
}
screen shot 2018-04-13 at 1 50 21 pm
3ygun commented 6 years ago

Thanks @rfrew! For a OAuth2 grant_type=password I did the following. On a Collection added a pre-request script of:

// From https://github.com/postmanlabs/postman-app-support/issues/2452
// pm.globals.get()

if(pm.environment.get("token_time") <= Date.now()) {
    var body = 'grant_type=password'
            + '&client_id=' + pm.environment.get("clientId")
            + '&client_secret=' + pm.environment.get("clientSecret")
            + '&username=' + pm.environment.get("username")
            + '&password=' + pm.environment.get("password");
    // console.log(body);
    pm.sendRequest({
        url: pm.environment.get("oauth_url"),
        method: 'POST',
        header: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        },
        body: {
            mode: 'raw',
            raw: body
        }
    }, function (err, res) {
        pm.environment.set("oauth_token", 'Bearer ' + res.json().access_token);
        pm.environment.set("token_time", Date.now() + 60*60*1000); //60*60*1000 = 1hr in milliseconds
    });
}

In Environment, setup the following variables: (bulk edit view)

clientId:String
clientSecret:String
oauth_url:https://localhost/oauth2/token
username:String
password:String

In a requests, add the following to Headers: (bulk edit view)

Authorization:{{oauth_token}}
ggirard07 commented 6 years ago

This still does not solve the authorization flow where user needs to manually input its credentials in a web view...

seppestas commented 6 years ago

IMHO the pre-request script isn't a very sustainable solution. It's quite hard to make it work for all collections, setting all required variables in a collection's variables is kind of a pain and this has to be done every time a collection is added. Also a pre-request script will only be able to automatically refresh the token. AFAIK there is no way to have it display a button (unless maybe a dialog, but that's not really what I had in mind).

Adding this functionality to the already existing oAuth Authorization functionality makes a lot more sense to me since it already has a field for all required variables.

Personally I'm more a fan of having a manual refresh token button iof having the tokens refresh automatically, but having the option to do this would be nice as well. I wouldn't like Postman to turn into an untransparent automagical API client where things happen without the user knowing about it.

ggirard07 commented 6 years ago

Pre request script is also mandatory. When you have a big collection, token may expire during the execution. Having the possibility to refresh it from pre request is crucial in that case. In the case of the authorization flow, all the information required to refresh the token are stored outside the sandbox used to execute the script. To get it to work it is just a matter of forwarding the appropriate token information to the sandbox!

wdtracy commented 6 years ago

+1

We use code flow and none of the work-arounds help. Is there a way to programatically change the token that the auth processes uses? The token gets automatically added to the request headers but I don't see it in the environment variables.

ggirard07 commented 6 years ago

Most of the OAuth/OpenIDConnect issues are now almost 2 years old. Every few months they get labels added/removed but nothing is really moving in that area.

Moily commented 6 years ago

Now that OAuth2.0 w/ Client Credentials has been fixed this issue will be seen by many more devs.

It would be great to get this implemented. Auto-refresh / Manual refresh (configurable in the Token setup screen, preferably) would be very welcome.

bartlettcp commented 6 years ago

Arrrgh - I've just set up two different Oauth 2.0 Token's (with 60 min expiry) in 2 different Postman collections.

I then did some coding - and my tokens expired - so I went to regenerate them - to find that it only saves one set of settings (e.g Grant Type, Auth Url, Access Token URL, Client Id & Secret) - and the first set of settings are lost... This is really terrible - because the Secret is no longer retrievable and I have to generate another one.

My two different collections should not intefere with my 2 different OAuth settings... and I also notice that my 'Available Tokens' drop down is system wide - not collection or folder wide - why would this be?

Please, please, please change this so that these tokens and settings are relevant to where they are being used (or at least at a Collection level if you can't do Folder level) - some of these settings are not easy to recreate every time they are needed - and if you need 2 different tokens at the same time - it is super painful!

dromer commented 5 years ago

Since I'm currently unable to make the pre-request script work for refresh-tokens I'd also like to emphasize the importance of this in the oauth2 workflow.

ByPS128 commented 5 years ago

Hello, i am using several identity providers that serves access tokens. When some token expires it is very annoying to refill the fields at "get new access token" dialog. If the dialog will have something like template (via combobox for exampel) and I will have possibility to store dialog as named template or recall template to fill the dialog, I will very appreciate this. This functionality can be simple to develop and easy to use with very effective. Somethink like payment templates in internet banking. Thanks for taking a look at it.

mths0x5f commented 5 years ago

I have a dream that someday this will come to Postman, exactly how is done in Insomnia

jantonacci commented 5 years ago

Pivotal Spring Services tokens expire in 30 seconds. Spending more time refreshing tokens than running requests. Back to Python scripts.

Blkandwhtlion commented 5 years ago

Looks like this is tstill not implemented, is it on the roadmap? Refresh button and potentially an alternative config option to make refreshing automatic based on refresh time field. The best case it can read response for the expires_in field on most OAuth responses

WarrenFerrell commented 4 years ago

Hope this gets prioritized a little better. This essentially makes the built in Auth useless for a large number of applications

DnlCYan commented 4 years ago

This would be a great feature to add on Postman. I always used Postman with workaround authentication creating a specific request for authentication and save the access token on the environment to be used on my actual requests. So avoiding the use of Authorization tab. It works great for grant_type client_credentials and password. But now I have a project that needs grant_type authorization_code, using this workaround doesn't work in this case because it tries to open the necessary login web view. Unfortunately, my solution for this is to ditch Postman and start to use Insomnia, because Insomnia already handle this case perfectly.

SegarJJ commented 4 years ago

I run the same pattern as others in this thread. When a colleague opens any of our numerous shared workspaces and environments, and then runs a request they will use the previously set refreshtoken from most likely another user. This goes sideways.

The lesson is that every developer must first 'get new access token' as a requirement.... then they can start using requests in that workspace/collection.

There should be a way to script out of the "Get New Access Token' dialog in the oauth2 workflow, any ideas how?

sakhtar1979 commented 4 years ago

Any updates on this one? Atleast a reason that why it won't be done or its on roadmap will help.

TaylorDale commented 4 years ago

This seems like a large oversight, refresh tokens are a pretty integral part of the process. A fix could be quite easily made with preflight scripts if we had access to the refresh_token response of the OAuth endpoint

wizofaus commented 4 years ago

Agree, currently having to manually create new tokens every so often (and delete the old ones etc.) is a major pain. Auth-tokens aren't tied to your current environment either, which means having to constantly change them every time you test against a different environment.

AliArdaOrhan commented 4 years ago

Is there any update on this? Imho, It will really improve the experience API testing with OAuth 2.0.

anladwig commented 4 years ago

I am confused why this has been open for 4 years with no response of any type.

mtwomey commented 3 years ago

+1 Getting pushback in my group on the lack of this capability (specifically in the case of auth code grant flow).

esbenbach commented 3 years ago

In this other case of postman thinking "we are not going to respond to you for this reasonable feature request", someone started posting on twitter. Have a look at #2934

Don't know if that was a coincidence, but quickly thereafter a solution was provided. Maybe they only respond to public pressure :p

On the more serious side: Postman, please start at least responding and CLOSING stuff if you don't want to solve it, or update the issues regularly when people keep posting feedback or +1 or whatever.

Being able to have postman automatically handle token expiration times and possibly automatically using refresh tokens when required would be a timesaver for many of us.

ash007-postman commented 3 years ago

On behalf of a user:

Almost going to be a year, any plans for this?

Any update on this?

Looks like this is still not implemented, is it on the roadmap?

Any updates on this one? At least a reason that why it won't be done or it's on the roadmap will help.

Is there any update on this?

I am confused why this has been open for 4 years with no response of any type.

Maybe they only respond to public pressure :p

Postman, please start at least responding

@giridharvc7

giridharvc7 commented 3 years ago

We will start works on this soon. I'll update the roadmap here as things get solid.

alexrosenfeld10 commented 3 years ago

any update on this?

OblongLongjohns commented 2 years ago

any update on this?

anything?

davequested commented 2 years ago

+1 on handling the refresh_token with the OAuth2 Authorization code flow. Or even be able to store the refresh_token/expires_in values after the flow in the collection variables so we can create a pre-request script to handle the refresh. Currently we have to manually copy the refresh_token/expires_in out, and then paste into the collection variables.

tjveldhuizen commented 2 years ago

See also #10112

JamesMay6 commented 2 years ago

@giridharvc7 any update on its delivery? Or, a work around using pre-request script ?

savage-alex commented 2 years ago

+1 on handling the refresh_token with the OAuth2 Authorization code flow. Or even be able to store the refresh_token/expires_in values after the flow in the collection variables so we can create a pre-request script to handle the refresh. Currently we have to manually copy the refresh_token/expires_in out, and then paste into the collection variables.

I would like to see this feature too. Being able to store the output of the auth event would then allow us to use request scripts to handle the rest. I cant get the refresh token out (or inject one from something else easily other than copy paste) Once its there then everythings good.

nphase commented 2 years ago

Quite amazed this capability doesn't already exist. the "Monitor" feature in Postman is crippled without it for OAuth2 users!

+1 on request to bring to top of roadmap.

demoran23 commented 2 years ago

I work with Microsoft Dataverse a lot, which requires a scope. This mod to the pre-flight script is also a bit more robust than the original:

// source https://github.com/postmanlabs/postman-app-support/issues/2452

const clientId = pm.environment.get("client_id");
const clientSecret = pm.environment.get("client_secret");
const accessTokenUrl = pm.environment.get("access_token_url");
const scope = pm.environment.get("scope");
const accessToken = pm.environment.get("access_token");
const expiresIn = pm.environment.get("expires_in");
const shouldUpdate = !expiresIn || !accessToken  || (expiresIn <= Date.now());

// If we don't have enough configuration information defined, throw
const args = { clientId, clientSecret, accessTokenUrl, scope };
if (Object.values(args).some(v => !v)) throw Error(`Missing configuration value(s) in: ${JSON.stringify(args)}`);

if (shouldUpdate) updateAuthentication(args);

function updateAuthentication({ clientId, clientSecret, accessTokenUrl, scope }) {
    pm.sendRequest({
        url: accessTokenUrl,
        method: 'POST',
        header: {
            'Authorization': `Basic ${btoa(`${clientId}:${clientSecret}`)}`,
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        },
        body: {
            mode: 'raw',
            raw: `grant_type=client_credentials&scope=${scope}`
        }
    }, (err, res) => {
        if (err) {
            console.warn("Req failed");
            throw err;
        }

        // If we have an error member, we won't have an access token.
        const json = res.json();
        if (json.error) throw Error(`FAILED TO ACQUIRE ACCESS TOKEN.  ${json.error_description}`);

        pm.environment.set("access_token", json.access_token);
        pm.environment.set("expires_in", Date.now() + json.expires_in ?? 60*60*1000); // default to 1 hr if no expiry
    });
}
giridharvc7 commented 2 years ago

We are picking up this feature. Will keep this thead updated.