06-22-2020 16:42
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

06-22-2020 16:42
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi!
I haven't been able to figure out how to revoke a token when using PKCE. I'm setting the appropriate header (and the content-length is being included):
content-type application/x-www-form-urlencoded
and the body of the post request is:
client_id=ABC&token=XYZ
I'm receiving a 401 with the following response:
:method: POST
:scheme: https
:path: /oauth2/revoke
:authority: api.fitbit.com
accept: */*
content-type: application/x-www-form-urlencoded
cookie: JSESSIONID=90D21CDC3C73857254E8F9A7972A5BDA.fitbit1; fct=1cb8cf8010be45e69109e7f6daeb5fdb
accept-encoding: gzip;q=1.0, compress;q=0.5
user-agent: Paceline Demo/1.0 (guru.shyn.Paceline-Demo; build:1; iOS 13.1.0) Alamofire/4.9.1
accept-language: en;q=1.0
content-length: 256
client_id=XYZ&token=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkJNUEQiLCJzdWIiOiI4TDVaVzIiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZXYiLCJzY29wZXMiOiJyaHIgcmFjdCBycHJvIiwiZXhwIjoxNTkyODkzMDAxLCJpYXQiOjE1OTI4NjQyMDF9.qoOBqmJBUK_cRWlOjEfVR7IbV0wrBWPZaLP-V-oeGhs
06-23-2020 09:50 - edited 06-23-2020 09:51
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post



06-23-2020 09:50 - edited 06-23-2020 09:51
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi @swiftdev,
Looks like you had it working when you got the 200 response.
PKCE is only used to securely obtain the access token. After you obtain the access token, you should follow the syntax specified in our documentation or RFC 7009 to revoke the access token. Here's the link to our documentation: https://dev.fitbit.com/build/reference/web-api/oauth2/#revoking-tokens.
POST https://api.fitbit.com/oauth2/revoke
Authorization: Basic Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=
Content-Type: application/x-www-form-urlencoded
Content-Length: <size of message>
token=<access_token or refresh_token>
You need to remove the client ID parameter from the body parameters. We will read the client ID from the tokens provided.
Senior Technical Solutions Consultant
Fitbit Partner Engineering & Web API Support | Google

06-23-2020 10:31
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

06-23-2020 10:31
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hey Gordon, thank you so much from the reply!
I received the 200 when I added the authorization header, but I'd like to side step having to send the client secret to the iOS app, which is why I chose the PKCE flow. From the docs it seems I can skip the authorization header if I include the client_id and token in the body.
I just attempted to revoke a token and the body of the post was set to the token, and I did not include any additional headers except for the "content-type". This gives a different error:
{
"errors": [{
"errorType": "invalid_client",
"message": "Invalid authorization header format. The header was not recognized to be a valid header for any of known implementations or a client_id was not specified in case of a public client Received header = null. Visit https://dev.fitbit.com/docs/oauth2 for more information on the Fitbit Web API authorization process."
}],
"success": false
}
Here is the request and response when retrieving the token:
:method: POST
:scheme: https
:path: /oauth2/token
:authority: api.fitbit.com
accept: */*
content-type: application/x-www-form-urlencoded
accept-encoding: gzip;q=1.0, compress;q=0.5
user-agent: Shyn Demo/1.0 (guru.shyn.Shyn-Demo; build:1; iOS 13.1.0) Alamofire/4.9.1
accept-language: en;q=1.0
content-length: 229
client_id=22BMPD&code=7acaef73baad092c56095d09563831666f05155a&code_verifier=C77EqoAx85Jp4zFjcwYgKucbWg9IEliitWvYrG6Q4A21pY4zPwvq0dgSqOv_9sfHnm1XpDnnosVg9mvMiS-BEQ&grant_type=authorization_code&redirect_uri=Shyn%3A//authorize
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkJNUEQiLCJzdWIiOiI4TDVaVzIiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyaHIgcmFjdCBycHJvIiwiZXhwIjoxNTkyOTYxMzIyLCJpYXQiOjE1OTI5MzI1MjJ9.M_XmnbaCgciWyUKdIBEmxdZHozXM21rvOFDZMBsY2rA",
"expires_in": 28800,
"refresh_token": "b6bb2782dae36a696240e3ff6c8928285caace92f2dd95d9a77d710525186b6a",
"scope": "heartrate activity profile",
"token_type": "Bearer",
"user_id": "8L5ZW2"
}
And here is the request and response when trying to revoke the token:
:method: POST
:scheme: https
:path: /oauth2/revoke
:authority: api.fitbit.com
accept: */*
content-type: application/x-www-form-urlencoded
accept-encoding: gzip;q=1.0, compress;q=0.5
user-agent: Shyn Demo/1.0 (guru.shyn.Shyn-Demo; build:1; iOS 13.1.0) Alamofire/4.9.1
accept-language: en;q=1.0
content-length: 239
token=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkJNUEQiLCJzdWIiOiI4TDVaVzIiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyaHIgcmFjdCBycHJvIiwiZXhwIjoxNTkyOTYxMzIyLCJpYXQiOjE1OTI5MzI1MjJ9.M_XmnbaCgciWyUKdIBEmxdZHozXM21rvOFDZMBsY2rA
Response:
{
"errors": [{
"errorType": "invalid_client",
"message": "Invalid authorization header format. The header was not recognized to be a valid header for any of known implementations or a client_id was not specified in case of a public client Received header = null. Visit https://dev.fitbit.com/docs/oauth2 for more information on the Fitbit Web API authorization process."
}],
"success": false
}
The token I received:
eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkJNUEQiLCJzdWIiOiI4TDVaVzIiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyaHIgcmFjdCBycHJvIiwiZXhwIjoxNTkyOTYxMzIyLCJpYXQiOjE1OTI5MzI1MjJ9.M_XmnbaCgciWyUKdIBEmxdZHozXM21rvOFDZMBsY2rA
is identical to the token I sent to the revoke API:
eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkJNUEQiLCJzdWIiOiI4TDVaVzIiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyaHIgcmFjdCBycHJvIiwiZXhwIjoxNTkyOTYxMzIyLCJpYXQiOjE1OTI5MzI1MjJ9.M_XmnbaCgciWyUKdIBEmxdZHozXM21rvOFDZMBsY2rA
My goal is to be able to revoke the token in an iOS client without needing to have the client secret.
What do you think?!
Thanks again!

06-24-2020 22:58 - edited 06-24-2020 23:05
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post



06-24-2020 22:58 - edited 06-24-2020 23:05
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi @swiftdev
I believe this is suppose to work if the token being revoked is from a public client, as stated in the documentation. I cannot get this to work, so I'm creating a ticket for engineering to investigate. Also, I've created case 00001440 for this problem. You should have received an email to the address associated with this account. Check your spam folder if you don't see the email in your primary inbox. Feel free to reply to the email you received to get updates or ask questions.
Gordon
Senior Technical Solutions Consultant
Fitbit Partner Engineering & Web API Support | Google

08-17-2021 08:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post



08-17-2021 08:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
Hi @swiftdev
It looks like this problem is fixed. We should support the ability to revoke refresh/access tokens obtained via PKCE. Would you please verify this works for you?
Gordon
Senior Technical Solutions Consultant
Fitbit Partner Engineering & Web API Support | Google
