Is it possible to use JWT Bearer received from MSAL (MS identity platform) to access MS AppCenter API? - msal

I am writting Android app to call MS Appcenter API (https://openapi.appcenter.ms/) and want the users of the app to login with their credential so i can not use pregenerated tokens.
I am able to get JWT token using MSAL android library com.microsoft.identity.client:msal:0.2.2
If I try to call the API "https://api.appcenter.ms/v0.1/user" with Authorization: Bearer ... header I got response {"message":"Fail to verify JWT Token.","statusCode":401,"code":"Unauthorized"}
Neither X-API-Token works with the token (not a surprise)
It is interesting if I lookup JWT token from GoogleChrome dev tools and use it either with curl: curl -X GET "https://api.appcenter.ms/v0.1/user" -H "accept: application/json" -H "Authorization: Bearer ..." or hardcode into my android app I get success response.
So it is definitely possible to use "some" JWT token to access Appcenter API, but it is unclear is it possible to get working JWT token from MSAL and what I should use instead it if it is not possible.
My first suggestion is I have to use the correct "SCOPE" audience, but it is not documented and quick guesses did not help
The way I get JWT token from MSAL (have success to get it)
val SCOPES = arrayOf("email")
val authClientApplication = PublicClientApplication(context, clientId)
authClientApplication.acquireToken(
context,
SCOPES,
object:AuthenticationCallback {
override fun onSuccess(authenticationResult: AuthenticationResult?) {
Log.d(TAG, "Successfully authenticated");
Log.d(TAG, "ID Token: " + authenticationResult?.idToken);
token = authenticationResult?.idToken
}
...
The way I try to use the JWT token (fails with 401 if JWT got from MSAL)
val client = OkHttpClient()
val request = Request
.Builder()
.header("Authorization", "Bearer "+token)
.url("https://api.appcenter.ms/v0.1/user")
.build()
try {
client.newCall(request).enqueue(object: Callback{
...
JWT from MSAL decoded content (not-working):
{
"ver": "2.0",
"iss": "https://login.microsoftonline.com/XXXXXX-6c67-4c5b-b112-36a304b66dad/v2.0",
"sub": "AAAAANNNNNAAAAAAAAAAAAJgzlyDKyV8iUg4I-js52sY",
"aud": "long-numbers-of-azure-app-client-id",
"exp": 1561271401,
"iat": 1561184701,
"nbf": 1561184701,
"name": "My Name",
"preferred_username": "my#email",
"oid": "00000000-0000-0000-cd89-898098098",
"email": "my#email",
"tid": "long-numbers-of-something",
"aio": "BASE64lookingGarbage"
}
JWT from GoogleChrome session decoded content (working):
{
"id": "35980548-0000-4c1d-9d9c-2318dc17a4a1",
"origin": "appcenter",
"iat": 1561184258,
"exp": 1561187858,
"aud": "Bifrost",
"iss": "Heimdall",
"sub": "user"
}

Related

How do i get access token from wix

I am working on a wix website, so i need to access wix store API.
I need access token so be passed with the response
I have tried doing that with this https://dev.wix.com/api/rest/getting-started/authentication, but i am getting "invalid auth code"
{
"grant_type": "authorization_code",
"client_id": "***********",
"client_secret": "********",
"code": "*******"
}

Decoding jwt token returned by the new google identity api

I have created a login button with google identity javascript api https://developers.google.com/identity/gsi/web/guides/display-button#javascript
I have successfully returned a jwt token and decoded it successfully. I have a field in the jwt token called kid and the docs say this is its purpose
the thumbprint for the public key used to verify this token
Will the kid field always be the same for the email i logged in with and can it ever change?
I am looking to extract a field from the jwt that will never change so that i can track users who have logged in on web and on android apps.
Run the id token through Jwt.io The payload data should look something like this.
{
"iss": "accounts.google.com",
"azp": "1046123799103-q2fg15qscp8apoh8fcf490o3d0bk.apps.googleusercontent.com",
"aud": "1046123799103-q2fg15qscp8apoh8fcf490o3d0bk.apps.googleusercontent.com",
"sub": "117200475532672775346",
"email": "XXXXX#gmail.com",
"email_verified": true,
"at_hash": "LqL3dnsD9w-elE-unya7-g",
"iat": 1662038461,
"exp": 1662042061
}
In this example the sub is the users internal id on google.
If i run it though the token info endpoint
https://oauth2.googleapis.com/tokeninfo?id_token=Id_token
I get the same sub claim
{
"iss": "accounts.google.com",
"azp": "1046123799103-q2fg15qscp8apoh8fcf490o3d0bk.apps.googleusercontent.com",
"aud": "1046123799103-q2fg15qscp8apoh8fcf490o3d0bk.apps.googleusercontent.com",
"sub": "117200475532672775346",
"email": "XXXX#gmail.com",
"email_verified": "true",
"at_hash": "M_28bzozJTabf3e8Q1yyeQ",
"iat": "1662045590",
"exp": "1662049190",
"alg": "RS256",
"kid": "402f305b70581329ff289b5b3a67283806eca893",
"typ": "JWT"
}
Sub claim is normally used for account linking between the internal user system of a site and the external third party logins.
you can use base64url_decode function to decode your jwt like that, I had the similar problem that I've solve like that in symfony 5.3:
$jwt = $request->request->get('credential');
$match=explode('.',$jwt);
function base64url_decode($base64url)
{
$base64 = strtr($base64url, '-_', '+/');
$plainText = base64_decode($base64);
return ($plainText);
}
$payload=base64url_decode($match[1]);
$payloadObject=json_decode($payload);
$verif = $payloadObject->email_verified;
$email = $payloadObject->email;
...etc

How to get to get claims from JWT token without validation in Go

I have a JWT token with the claims below
{
"authorized": true,
"email": "sample#gmail.com",
"exp": 1589929351,
"node": "/auth/nodes0000000023",
"role": "admin"
}
The issuer of the JWT is the claims['node']. In the above claims it is the /auth/nodes0000000023.
How do I extract the issuer from the token without verifying the token.
I want to get the issuer name so that I can go find his publicKey from a map and then verify the token.
I have found the function func (*Parser) ParseUnverified in the docs, but it is unclear on how to use it.
The library used is github.com/dgrijalva/jwt-go
You can use the unverified parse API the same way you use the verified API:
tok,_,err := p.ParseUnverified(tokenString,&claimsStruct)

Send message from Postman to Microsoft Bot

I am trying to send a message to a bot I created and published to azure services so that the bot can then start messaging some of its users.
I am trying to make the requests on Postman first so that then I can build a controller for that interaction.
I am doing the following request:
POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Body:
grant_type:client_credentials
client_id: my_ms_app_id
client_secret: my_ms_app_secret
scope: https://api.botframework.com/.default
from this I get in the response the Bearer Authorization:
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 0,
"access_token": "eyJ0eXA..."
}
Then I proceed with the following request:
POST https://skype.botframework.com/v3/conversations
Content-Type: application/json
Authorization: Bearer eyJ0eXAi....
{
"bot": {
"id": "i don't have this id so i pass some string",
"name": "connector controller"
},
"isGroup": false,
"members": [
{
"id": "28:...", //ID of the bot I want to send the message to
"name": "Sp Bot"//Name of the bot I want to talk to
},
{
"id": "i don't have this id so i pass some string",
"name": "connector controller"
}
],
"topicName": "News Alert"
}
in response i get the conversation id which matches "id": "i don't have this id so i pass some string":
{
"id": "i don't have this id so i pass some string"
}
Then I proceed with the following POST request:
POST. https://skype.botframework.com/v3/conversations/i don't have this id so i pass some string/activities
Authorization: Bearer eyJ0...
Content-Type:application/json
I get the following response:
400 Bad Request
{
"error": {
"code": "ServiceError",
"message": "The conversationId 29... and bot .... doesn't match a known conversation"
}
}
It looks like the problem occurs between the second and the 3 post method. It looks like that the https://skype.botframework.com/v3/conversations does not generate a conversation with the bot with Id I entered.
So when I make the final call to the bot: https://skype.botframework.com/v3/conversations/.../activities I always get the serviceError message.
Based on your comments you are trying to create a custom "channel/client" to talk with the bot.
For doing that, I would recommend taking a look to Direct Line which seems the way to go for achieving your requirement.
I'm not sure which language are you using, so I will send you pointers to both C# and Node.
These are samples that will show you how to create custom client using Direct Line to interact with your bot:
C#
Basic Direct Line sample
Direct Line sample using Web Sockets
Node.js
Basic Direct Line sample
Direct Line sample using Web Sockets
All the samples are using a console app as the "custom channel".
Since you're going to make an app talk to your bot and most likely be using DirectLine after you and Ezequiel chatted, I created a series of screencaps on connecting to the DirectLine endpoint through Potsman. I'm going to assume that you know how to use environmental and global variables in Postman, here are Postman's documentation for other people's benefit. Also, the DirectLine v3.0 docs are here.
Below is a capture of the directline endpoint you would request a token from, {{DLsecret}}'s guts looks like this, Bearer <your-dl-secret>:
Here is an example of the response body you would receive on a valid call:
You may have noticed that I have some test results, in the screenshow below it has five (vs four) tests because I added the test verifying that the conversationId was set in the environment variables:
Here's the second query sent, which contains an actual message:
This is the request body which has the message:
And here is the response body:

Adsense API getting 'Error: Login Required'

I'm using the API Explorer tool to create some request urls for google adsense. Here is the request url that the explorer tool generated that gives a response of today's earnings: https://www.googleapis.com/adsense/v1.4/reports?startDate=today&endDate=today&accountId=MY_ACCOUNT_ID&metric=EARNINGS&key=MY_API_KEY
However, when I try to use this url in the browser or in my code it gives this response:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
I am not sure what I am missing it use this url. I have activated adsense apis on my google developer console.
The key parameter is the public API key for accessing public data.
The access_token parameter is used for accessing private user data.
In your case you are trying to access your private account and should be using an access token.
To obtain an access token you need to authentication your application using either Oauth2 or a service account. Once you have obtained an access token and send that with your request as so:
https://www.googleapis.com/adsense/v1.4/reports?startDate=today&endDate=today&accountId=MY_ACCOUNT_ID&metric=EARNINGS&access_token=YourAccessToken
You need to replace MY_API_KEY with your API key, and MY_ACCOUNT_ID in same fashion.

Resources