These forums have been archived and are now read-only.

The new forums are live and can be found at https://forums.eveonline.com/

EVE Technology Lab

 
  • Topic is locked indefinitely.
 

How to handle expiring ESI tokens?

First post
Author
Ilvari
GoonWaffe
Goonswarm Federation
#1 - 2017-02-12 16:51:23 UTC  |  Edited by: Ilvari
I'm currently moving a Windows application that used to use the XML API to ESI.

How it used to work is the same way as Evemon etc work. The application sends the user to https://community.eveonline.com/support/api-key/ , where he gets an API key, enters it in the option dialog and the application then keeps using the key for its queries. The users are recommended to create non-expiring keys but of course they can limit the keys validity to a point a few months in the future or similar if they want more security. It doesn't really matter, the application still works for a decent amount of time.

For ESI, what I am doing so far is sending the user to
https://login.eveonline.com/oauth/authorize?response_type=token&redirect_uri=https%3A%2F%2Fwebsite.com%2Ffiles%2Fcallback.html&realm=ESI&client_id=7761e5f9123b49d98c0bf36f4e144e1d&scope=esi-markets.structure_markets.v1
instead. There, he authorizes the app and gets send back to a placeholder website that displays the auth token to be entered in the application.

After that auth token is entered, the application is then able to query the API with that key with queries like
curl -i --compressed -X GET --header "Accept: application/json" --header "Authorization: Bearer YA2V800000000000000000000jcdPU2fgLg_8ll6eDsOgCTqDPrTqrkMEwg2" "https://esi.tech.ccp.is/latest/markets/structures/1020000000176/?page=1&datasource=tranquility"


That works just fine and returns the JSON results I need. But only for 20 minutes.
After that, the token expires and the ESI query only returns a 403.
I have to send the user again to the authorization page to get a new key.
Every. Twenty. Minutes.

Is that really the intention behind this new system? I noticed that the Eve Online Swagger interface works the same way, where you have to keep logging in every 20 minutes. But can we really expect our users to have to keep re-authenticating 50 times a day?
Steve Ronuken
Fuzzwork Enterprises
Vote Steve Ronuken for CSM
#2 - 2017-02-12 18:58:08 UTC
Not at all.

You want the refresh token. An Access token is valid for 20 minutes. The refresh token is valid until revoked, and can be used to generate access tokens at will.

https://eveonline-third-party-documentation.readthedocs.io/en/latest/sso/refreshtokens.html

Woo! CSM XI!

Fuzzwork Enterprises

Twitter: @fuzzysteve on Twitter

David Davaham
Deep Blue Logistics
#3 - 2017-02-13 00:30:48 UTC
OMG no

I am not sure how to do it for desktop applications, but what i have heard is that you need to make your callback http://localhost. Make sure you pick a random port number to listen on as well. Something in the tens of thousands. Have them click on a button that they authorize in your application with. They click that button, authorize the app and then they are redirected back to the localhost address that you have as your call back. Display an html website or something that is easy. Take the accessToken and refreshToken that you receive from that and make calls to the /auth/token endpoint to get a new accessToken every 19 minutes or how ever often you want to do. You just have to make sure you have some sort of method of make and receive calls using HTTPS from you application without it hindering user experience.

Developer of EVEmail

Steve Ronuken
Fuzzwork Enterprises
Vote Steve Ronuken for CSM
#4 - 2017-02-13 02:30:13 UTC  |  Edited by: Steve Ronuken
David Davaham wrote:
OMG no

I am not sure how to do it for desktop applications, but what i have heard is that you need to make your callback http://localhost. Make sure you pick a random port number to listen on as well. Something in the tens of thousands. Have them click on a button that they authorize in your application with. They click that button, authorize the app and then they are redirected back to the localhost address that you have as your call back. Display an html website or something that is easy. Take the accessToken and refreshToken that you receive from that and make calls to the /auth/token endpoint to get a new accessToken every 19 minutes or how ever often you want to do. You just have to make sure you have some sort of method of make and receive calls using HTTPS from you application without it hindering user experience.



For desktop apps, this is one way to do it, yes.

You do _not_ want to do the username/password entry within the application itself. This is a massive security risk, and I'll yell about any applications I see that do this. (Personal use is fine, but not if you distribute it)

Send the user to their system browser. Have them auth there, have it send it back to your app in one of the following manners:

Embed a webserver: This is a fairly easy, and portable. It's not the easiest of things to do, but it works.

Define a custom url scheme, and use that to get back to your application. So your callback url is something like myawesomeapp://localhost/auth And that's set to open up your application, and auth it.

The second is a touch more complicated to do, as you'll need to work out how to register it, and have a way to pass the auth over from a second instance of the app, to the one that started things.

https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx covers registering it on windows. Most installers have a way to do this.

As for the second part, one way is to open up socket when the app starts. If you can't bind it, then it's the second instance, and you pass the auth over via the socket.


An alternate method is to handle the auth entirely on a webserver, and just present the refresh token to the user, who can then copy and paste it into the local app. (in the same way you'd do an api key)

Woo! CSM XI!

Fuzzwork Enterprises

Twitter: @fuzzysteve on Twitter

Ilvari
GoonWaffe
Goonswarm Federation
#5 - 2017-02-13 19:42:44 UTC
Thanks, I figured it was silly if we had to do it that way, but because Swagger works like that I was a bit concerned.

Just for reference, how I'll be doing it:
1. Send the user to https://login.eveonline.com/oauth/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwebsite.com%2Fcallback.html&realm=ESI&client_id=776000000000098c0bf36f4e144e1d&scope=esi-markets.structure_markets.v1

He authorizes the app, then gets redirected to a website that fetches the code from the URL and displays it to the user. The user then copy & pastes the code into the application

2. Upon entering the code, have the application do a
curl -i --compressed -X POST --header "Accept: application/json" --header "Authorization: Basic NzcsMw==" --data "grant_type=authorization_code&code=P-tux11g4Qo0000000000000000YtpYWYPu0" "https://login.eveonline.com/oauth/token"
request with that code, then discard the code, and store the refresh_token

3. Next, ever time the API needs to be queried, do a
curl -i --compressed -X POST --header "Accept: application/json" --header "Authorization: Basic NzcMw==" --data "grant_type=refresh_token&refresh_token=UKmRhoj0000000000000000000Wdr9H_vI5Q1" "https://login.eveonline.com/oauth/token"
to get an access token

I don't really want to go through the effort of having to include an entire HTTP server (and then be responsible for its security) with a little app. Using a pre-existing website to do that seems to be the smarter choice.
Steve Ronuken
Fuzzwork Enterprises
Vote Steve Ronuken for CSM
#6 - 2017-02-13 20:56:01 UTC
Ilvari wrote:
Thanks, I figured it was silly if we had to do it that way, but because Swagger works like that I was a bit concerned.

Just for reference, how I'll be doing it:
1. Send the user to https://login.eveonline.com/oauth/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwebsite.com%2Fcallback.html&realm=ESI&client_id=776000000000098c0bf36f4e144e1d&scope=esi-markets.structure_markets.v1

He authorizes the app, then gets redirected to a website that fetches the code from the URL and displays it to the user. The user then copy & pastes the code into the application

2. Upon entering the code, have the application do a
curl -i --compressed -X POST --header "Accept: application/json" --header "Authorization: Basic NzcsMw==" --data "grant_type=authorization_code&code=P-tux11g4Qo0000000000000000YtpYWYPu0" "https://login.eveonline.com/oauth/token"
request with that code, then discard the code, and store the refresh_token

3. Next, ever time the API needs to be queried, do a
curl -i --compressed -X POST --header "Accept: application/json" --header "Authorization: Basic NzcMw==" --data "grant_type=refresh_token&refresh_token=UKmRhoj0000000000000000000Wdr9H_vI5Q1" "https://login.eveonline.com/oauth/token"
to get an access token

I don't really want to go through the effort of having to include an entire HTTP server (and then be responsible for its security) with a little app. Using a pre-existing website to do that seems to be the smarter choice.



To neaten it up a little, I'd present the refresh token to the user to copy and paste, rather than the access code.

Just means you're always working with that, rather than having to provide a route to provide an access code, which requires the storage of an refresh token.

Woo! CSM XI!

Fuzzwork Enterprises

Twitter: @fuzzysteve on Twitter