Clarification on access token expiration

Hi @Cretcheu,

Good questions! Ok, the default access_token lifetime is about 90 days, we’re planning on extending that feature so you can set an arbitrarily long lifetime of the token, to simplify things. We’ll also provide wrappers for these in the CLI so you don’t have to use something like curl. :slight_smile:

If you’re writing an iPhone app, you can model it after the Spark-ios app here: https://github.com/spark/ios-app

In that app the user logs into their account, creating an access token for the program. You could also say just store your own credentials in your app, and ask for a new token every X days, etc.

There is some security reasoning behind the access_token expirations. Users will have the ability to arbitrarily invalidate any access_tokens they want when using their credentials, so if a user gives an app permission to use a core, that user can also take that permission away. The expirations help prevent dozens or hundreds of forgotten access_tokens from sitting around forever. It’s important that an app using an access_token should be aware of that possibility. We’re using a standard authentication / token system called OAuth http://oauth.net/

I hope that helps! :smiley:

Thanks,
David

1 Like

David,
Thank you. Yes your post was very helpful. I looked at the IOS App. Is this the code snippet I need? The Login and Register functions below?
Before I start on this how long before we will have longer living tokens?
What would also make things easier is if tokens were renewed instead of replaced. Just a thought.

- (void)login:(void (^)(NSString *))success failure:(void (^)(NSString *))failure
{
    NSDictionary *params = @{
                             @"grant_type": @"password",
                             @"username": self.user.userId,
                             @"password": self.user.password,
                             };

    [self setAuthorizationHeaderWithUsername:SPK_CLIENT_USERNAME password:SPK_CLIENT_PASSWORD];
    [self callMethod:@"POST" path:@"oauth/token" parameters:params notifyAuthenticationFailure:NO success:^(NSInteger statusCode, id JSON) {
        [self clearAuthorizationHeader];
        success(JSON[@"access_token"]);
    } failure:^(NSInteger statusCode, NSDictionary *dict) {
        failure([dict[@"errors"] componentsJoinedByString:@" "]);
    }];
}

- (void)register:(void (^)(NSString *))success failure:(void (^)(NSString *))failure
{
    NSDictionary *params = @{
                             @"username": self.user.userId,
                             @"password": self.user.password,
                             };
    [self callMethod:@"POST" path:@"v1/users" parameters:params notifyAuthenticationFailure:YES success:^(NSInteger statusCode, id JSON) {
        [self login:success failure:failure];
    } failure:^(NSInteger statusCode, NSDictionary *dict) {
        failure([dict[@"errors"] componentsJoinedByString:@" "]);
    }];
}

Hi @Cretcheu,

Cool! I think those are the relevant snippets, yes! The login function is just making a post to “https://api.spark.io/oauth/token” with the user credentials, and getting back an access_token.

Access token upgrades are on the feature backlog for this summer. I like the idea of renewing tokens, I would just want to make sure we weren’t breaking any OAuth rules, but otherwise it seems like it would be fine. I’ll make a note for myself to update this thread when the API lets you set the expiration time when creating an access_token.

Thanks!
David

David,

I’m close but I am missing some key concept.

I have https://API.spark.io/oauth/token… returning an access token. However each time I invoke it I get a different token. When I go into the Build IDE and check the access token in settings for my app it is still the old token. So, what are the tokens I am retrieving associated with? How do I use them vs. the one shown in the IDE.

I thought when I retrieved a token it would be the existing token. Then I thought, oh, it must be doing a reset. But neither seem to be the case.
Thanks,

Hi @Cretcheu,

Good question! The /oauth/token endpoint is the “Please create a new access_token for me” endpoint. You can list your access tokens using this endpoint described here: http://docs.spark.io/api/#authentication-list-all-your-tokens

Thanks!
David

1 Like

David,
Okay, so I say create a new access token for me and I get it. Now how do I replace/reset my existing token with my new token?
Second question, how do I get my existing token programmatically?
I’ve looked thru SPKWebClient.m and can’t seem to find a function that is doing either.

Thanks,

David,
Let me first apologize for all the questions but the more I delve into this the more questions arise. I now have the code working to retrieve all my tokens. So now I have all these listed below from requesting tokens. I requested them all the same way, yet they show three different clients, spark, spark-IDE and user. What does client mean? The token with client : user is the one my app is using. How does client get set? What would be the purpose of having multiple tokens? What is the HTTP call to reset the token to one that I have retrieved?

The documentation on this topic needs to be expanded beyond just the mechanics of retrieving, listing and deleting token to include the process for managing tokens via HTTP.

Thanks,

HTTP/1.1 200 OK
Server: nginx/1.6.0
Date: Wed, 02 Jul 2014 13:28:44 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1483
Connection: keep-alive
X-Powered-By: Express
Access-Control-Allow-Origin: *
ETag: "1238487029"

[
  {
    "token": "redacted",
    "expires_at": "2014-06-09T02:49:55.660Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-06-09T02:58:17.516Z",
    "client": "spark-ide"
  },
  {
    "token": "redacted",
    "expires_at": "2014-06-12T18:13:21.959Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-24T13:33:30.937Z",
    "client": "user"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-24T13:27:51.597Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-24T13:30:35.963Z",
    "client": "spark-ide"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-29T20:00:51.251Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-29T20:01:46.992Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-29T20:06:29.637Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-30T01:54:43.097Z",
    "client": "spark"
  },
  {
    "token": "redacted",
    "expires_at": "2014-09-30T02:05:06.274Z",
    "client": "spark"
  }
]

Hi @Cretcheu,

If you just need access for your app, you can simply create and store an access token using the user credentials in your app. When that token expires, or sometime before, you can repeat the process to get a new access token. I “redacted” your access_tokens that you posted because that’s about the same as posting your password publicly. :slight_smile:

It is more correct to cache and re-use the token you requested than it is to constantly re-pull the entire list of access tokens.

Client refers to the name of your app. You can read up more on the terminology here: http://hueniverse.com/oauth/guide/terminology/

I hope that helps!

Thanks,
David

1 Like

David,
I have token access working on the iPhone… Thanks!
But now I’m trying to get it working from my web client. I believe the header authorization is not correct. I have tried a number of permutations without success. Can you take a look and tell me what is wrong with the code?

Thanks,

$(document).ready(function(){
 $("button").click(function(){
   $.post("api.spark.io/oauth/token",
   {
     grant_type:"password"
     username:"redacted.com"
     password:"redacted"

   },
   function(data,status){
   doucment.write = status;
     alert("Data: " + data + "\nStatus: " + status);
     beforeSend: function(xhr) {
      xhr.setRequestHeader("Authorization", "Basic " + encodeBase64("spark" + ":" + "spark")); },
   });
 });
});

HI there @Cretcheu - By coincidence, @Dave just signed off two minutes ago for the Holiday weekend. I’ve got big bad @jgoggins on call, and he’s gonna take a look at this too. We don’t want to leave you hanging for the whole weekend :slight_smile:

1 Like

Okay. So, I wasn’t exactly sure about the required params either, so I started digging into the spark-cli source code to figure it out. I found this:

https://github.com/spark/spark-cli/blob/master/js/lib/ApiClient.js#L133

Which told me all I needed to construct a curl request to illustrate the endpoint in action:

curl -X POST https://api.spark.io/oauth/token \ 
  -d 'username=<YOUR_PASSWORD> \ 
  -d 'password=<YOUR_PASSWORD>' \ 
  -d 'grant_type=password' \
  -d 'client_id=<WHATEVER>' \
  -d 'client_secret=<WHATEVER>'

the client_id and client_secret can be whatever you want.

Hope that helps. Happy Hacking.
-joe

2 Likes

Hi sorry to raise an old thread,

I am wondering what the system offers when I have multiple cores I currently have one and have two more on order. The id and authorisation code are stored in a mySql database. These are accessed by a front end application written with Access. My hope is to have several hundred of the cores in my database controlling machines out in the field. May I ask you to explain to me how I can chose which core to renew the token on, all of the cores will be registered to one account. Ideally I would like to automate renewing codes and store the results in my database any thoughts on that would be much appreciated too.

Best regards,
Clive

My access token expired on me today, no letter, no email, no text… just ran off.

It’s the making of a country music song… "My token departed, it was a heck of a time…

2 Likes

Hi Dave;

Is that possible to request the access token expiration time now upon login or still 90 days default. If possible please let me know how. Thanks.

You can use CLI via particle token or look in the docs for the API
https://docs.particle.io/reference/api/#generate-an-access-token

Your default token for Build will live forever - unless you revoke it.

@ScruffR, I saw that document. I did not see any place I can make a curl request so that my access token won’t expire. I have tried this:

$ curl https://api.particle.io/oauth/token -u particle:particle -d grant_type=password -d username=joe@example.com -d password=SuperSecret

It is returning “expires_in”: 7776000

Thanks.

Have you tried the particle token way?
This should provide some better readable info.

That number is seconds till expiry (7776000sec = 90days)

BTW, that doc states

1 Like

@ScruffR, yes, I saw 0 means forever. The question was how do I get it to return 0.

That would be the one to list all your tokens
https://docs.particle.io/reference/api/#list-access-tokens

And when generating a new one, you’d need to add expires_in=0

curl https://api.particle.io/oauth/token -u particle:particle -d grant_type=password -d username=joe@example.com -d password=SuperSecret -d expires_in=0

Then it will return 0!

1 Like

@ScruffR, thanks. that helps.