Clarification on access token expiration

The more I read the more confused I get. Looking for some specific answers.

  1. Does reset provide a new token or reset the clock on the existing token?
  2. How can expiration be avoided?
  3. I will have iPhone and web apps communicating with Core. How do I prevent interruption of service?
  4. What else don’t I understand about access token expiration that can affect a running app?

Please provide some specific example that I can implement.

Thank you

2 Likes

In this doc section:

http://docs.spark.io/api/#authentication-generate-a-new-access-token

You will see how to get an access token and its expiry time by using the user credentials (username and password). Your app can prompt the user for these credentials, do the POST for an oauth token, and then use that token until it expires. You can then ask the user to re-authenticate and enter their username password again.

I believe that reset gives you a new and different token. I don’t think the expiration can be avoided currently. You iPhone app can ask the user to authenticate.

1 Like

Just to be clear, there are two different sets of numbers:

  • Device ID
  • Access Token

The DeviceID is locked to the hardware, and should basically never change. I think I have seen a reference to the ability of it to change, but I think (hope) this is the exception.

The Access Token is returned/created when you send your username and login. it is generated through oauth, and more details should be available through looking at the documentation for oauth. The best way to learn about it is to play with the ‘curl’ code to see what is going on.

Getting users to enter a username and password would give them a new access token each time they enter the credentials, but this might not be what you want, since you probably want to control the cores yourself, and only give them access to individual cores.

For my use case, things are easy - I only use Spark for firmware updates. All else comes through my own server. Then I have full control of what I give access to. In this case, all Cores are registered to the one account, and no one but me has access to it.

I really don’t understand how to accomplish updating the access token. This process seems very convoluted to me. It does not lend itself to creating a self sustaining application. Or am I not understanding?

For instance I will have an iPhone app talking to the core that is monitoring my garage doors. Specifically how do I update the access token in a seamless fashion so 1. The app does not stop working and 2. I don’t have to manually update the access token known to the app every 89 days?
I have looked at the curl example but don’t see how that is applicable.

Help getting thru this rabbit hole would be appreciated.
Thanks,

I don’t think the Spark guys have exposed a function to renew a token. You can create additional ones at any time with the API call to https://api.spark.io/oauth/token. One option would be to distribute a new key out of band through a web service, although I don’t think this is the most secure way of doing things.

Ultimately though a solution depends on your use case. If this is for your private use then the solution might be easier than if it is for a product to be distributed.

For instance, you can put javascript code on the on-load to use the stored username and password to get the access token at run time. I dont know that this is the best way of doing things, but it might work

I’d appreciate it if some one from Spark would weigh in on this. I can not be the only one with this problem. I don’t have the expertise to solve this on my own, nor will the majority of non Elite users. I can build a project, write the code and wire the board but building custom API’s to manage tokens is beyond me. If this was easy and well thought out it would be part the firmware. The fact that it is not makes using the Core in any project a high maintenance issue and at this point, for me a show stopper.

Spark team, help please. Need a tutorial!

I’m not sure what’s the complication here.

What’s the problem you are facing with access token management?

The API is already there I believe but yet to be exposed. I have already opened an issue to add this function in Spark-CLI and the API should be available.

What are you trying to do where the access token is the show stopper?

The access token when expired after I think 3 months, can simply be updated with a new one. I remember being able to generate new access token and even deleting them via API call.

Only the wrappers are missing I guess. Curl commands can do it.

The show stopper is that I cannot create a project that can run for more than 89 days.
The issue is I don’t know what specific steps to take to

  1. Set up my iPhone app to dynamically update the access token just before it expires every 89 days.
    This is an issue of lack of knowledge or understanding. I can write code in objective-C for the iPhone and I can write code for the Core. What I don’t understand is what code to write or how to structure it. If this is a no-brainier could some one please give me a concrete example or some sample code, 'cause I don’t get it. Show me the code you use to address this problem and how you implement it.

Thanks

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