Social Login using Google and Facebook in Flutter App - flutter

I am trying to implement my own server authentication (email, password) along with Facebook, and Google login. I would like to list what I have searched. Facebook login only returns an access token while Google login returns an access token and an id token.
I am planning to create my own JWT token in the backend, so which parameters (id token/access token) should be passed to my backend server to verify if the end user is logged in using Facebook or Google? I have some confusion about whether the access token is being used for authorization instead of authentication.

The token you get from google and facebook contain user data eg email, profile image etc you need to decode them.
Assuming email is unique in your db then you can query if exists and generate tokens on success.
example on how to decode google tokens in python
TLDR
from google.oauth2 import id_token
from google.auth.transport import requests
# (Receive token by HTTPS POST)
# ...
try:
# Specify the CLIENT_ID of the app that accesses the backend:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
# Or, if multiple clients access the backend server:
# idinfo = id_token.verify_oauth2_token(token, requests.Request())
# if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]:
# raise ValueError('Could not verify audience.')
# If auth request is from a G Suite domain:
# if idinfo['hd'] != GSUITE_DOMAIN_NAME:
# raise ValueError('Wrong hosted domain.')
# ID token is valid. Get the user's Google Account ID from the decoded token.
userid = idinfo['sub']
except ValueError:
# Invalid token
pass
Response
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}

Related

get Id ( not clientId) from keycloak jwt token

JWT only gives the user information and clientId, how can I get ID of the client as shown in the image
I CAN GET CLIENT DETAILS PARTICULARLY ID FROM THIS URL
https://${SERVER_URL}/auth/admin/realms/master/clients?clientId=test
API RESPONSE
{
"id": "12af651d-f6fe-49ef-8e6f-b951a49ff7db", // want to add this id into JWT
"clientId": "test",
"rootUrl": "${authBaseUrl}", ......
}
but I want to save my api call for getting Id
How can I get client information "Id" within jwt?
Now this is showing on the extraction of jwt
{
exp: 1627981808,
iat: 1627974608,
sub: '923666de-0b37-42f0-b694-0491028d0b78', // user Id
typ: 'Bearer',
azp: 'test', // client id
acr: '1',
scope: 'openid email profile',
email_verified: false,
name: 'name123',
preferred_username: 'name123',
given_name: 'name123',
email: 'any_name#gmail.com'
}
Any help/information will be helpful for me.
You should create and deploy a SPI to your keycloak instance. That's a JAR that overrides standard behaviour. There are various SPIs both described in the documentation and as code in GitHub keycloak repo.
With that SPI you can add just about anything to your token. I would suggest not to change anything that exists in the default token as this might impact your OID compatibility.
See more details here and here.

How can I a Google Api restful endpoint using service key?

I'm using postman to memic a restful api call and trying to access google sheets API end point. When I try to access my endpoint it returns:
{
"error": {
"code": 403,
"message": "The request is missing a valid API key.",
"status": "PERMISSION_DENIED"
}
}
which is fair enough as I did not use my API key. I created a service account and got a json file, but I plan to access using a rest endpoint so need to pass token in header but I'm not sure how.
I looked at the json file and wasn't sure what to extract in order to pass it for my rest call.
Has anyone been able to do this successfully?
Before calling Google Services from Postman, you would need to re-create the flow for getting an access token form service account credentials :
build and encode the JWT payload from the data from credentials files (to populate aud, iss, sub, iat and exp)
request an access token using that JWT
make the request to the API using this access token
You can find a complete guide for this flow is located here: https://developers.google.com/identity/protocols/oauth2/service-account#authorizingrequests
Here is an example in python. You will need to install pycrypto and pyjwt to run this script :
import requests
import json
import jwt
import time
#for RS256 you may need this
#from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
#jwt.register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))
token_url = "https://oauth2.googleapis.com/token"
credentials_file_path = "./google.json"
#build and sign JWT
def build_jwt(config):
iat = int(time.time())
exp = iat + 3600
payload = {
'iss': config["client_email"],
'sub': config["client_email"],
'aud': token_url,
'iat': iat,
'exp': exp,
'scope': 'https://www.googleapis.com/auth/spreadsheets'
}
jwt_headers = {
'kid': config["private_key_id"],
"alg": 'RS256',
"typ": 'JWT'
}
signed_jwt = jwt.encode(
payload,
config["private_key"],
headers = jwt_headers,
algorithm = 'RS256'
)
return signed_jwt
with open(credentials_file_path) as conf_file:
config = json.load(conf_file)
# 1) build and sign JWT
signed_jwt = build_jwt(config)
# 2) get access token
r = requests.post(token_url, data= {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": signed_jwt.decode("utf-8")
})
token = r.json()
print(f'token will expire in {token["expires_in"]} seconds')
at = token["access_token"]
print(at)
Note the value of the scope: https://www.googleapis.com/auth/spreadsheets
Probably, you can do all the above flow using Google API library depending on what
programming language you prefer
The script above will print the access token :
ya29.AHES67zeEn-RDg9CA5gGKMLKuG4uVB7W4O4WjNr-NBfY6Dtad4vbIZ
Then you can use it in Postman in Authorization header as Bearer {TOKEN}.
Or using curl :
curl "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Note: you can find an example of using service account keys to call Google translate API here

Generate access token using JWT

I've been given access to an okta token endpoint. I would like to use this service to request a token. I was given a url, client id, client secret, scope and grant type. I can use postman to make a POST call to the url (/v1/token) and pass the above info (client id, client secret, scope and grant type) and I get an access token back.
I can easily make this call in java with RestTemplate or equivalent, but I would like to use an API that would manage the token for me.
I've found JJWT. All the examples I see out there show me how to create a JWT using JJWT. What I would like to do is to get my access token, but I'm not sure how to do that. I mean i get that JJWT is an API to create JWT, but then how can I use the JWT to get my access token?
Any help/clarification/direction is much appreciated.
We using JWT with the node.js, to create new Token jwt.sign(data, key) takes at least to an argument, the fist must be some credential like userId, email..., the second will be key to verify later. to verify the token is it valid we use jwt.verify(), the first argument is token (where the jwt.sing() give you) and the second is the key (where you provide when creating);
example:
Creating JWT token:
var jwt = require('jsonwebtoken');
cosnt token = jwt.sign({ email: 'test#test.com', userId: '993333' }, 'secretkey');
verifying Token:
try {
const decodedToken = jwt.verify(token, 'secretkey');
}
catch(err) {
throw new Error(err)
}
// once verified
conosole.log(decodedToken)
I found this post how to create and verify token using java, thanks!

Gsuite Directory API 403 Error on API call or Grant Type Error on JWT Generation

Using Python and creating my own JWT using HTTP/Rest methodology, I simply can't get delegation to work.
On one hand, google JWT troubleshoot documentation says that ISS needs to be the same as the SUB (the service account).
However, on the server to server oauth2 documentation, it says that to impersonate an account, the sub needs to be the account I am attempting to impersonate in the claim.
Needless to say, despite enabling domain-wide delegation, adding the correct scopes, etc, I get nothing back but 403 when attempting to access the user domain utilizing the requests library in python with the following example:
> requests.get("https://www.googleapis.com/admin/directory/v1/users/useremail#/
> google.org",headers={'Authorization':f' Bearer {oauth2tokenhere}'})
Here is an example of my claim:
> claim = { "iss": 'serviceaccountemail',
> 'sub': 'impersonatedaccountemail',
> 'scope': 'https://www.googleapis.com/auth/admin.directory.user.readonly',
> 'exp': ((datetime.datetime.today() + datetime.timedelta(minutes=60)).timestamp()),
> 'iat': ((datetime.datetime.today()).timestamp()),
> 'aud': "https://oauth2.googleapis.com/token"
> }
The above claim will generate a generalized grant error (cute, but not helpful).
If I change the claim and ensure that the sub and the iss are the same, the oauth2token generates, but I get a 403 error when attempting to hit the API.
Here is the server to server oauth2 documentation stating the sub should be the
account the service account is attempting to impersonate.
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
Here is the troubleshooting article outlining the ISS/Sub being the same (although cloud article is the closest relevant topic I could find)
https://cloud.google.com/endpoints/docs/openapi/troubleshoot-jwt
EDIT:
I am utilizing the service account information from the downloaded .json file that is downloaded when creating the service account file.
import json as j
import datetime
import jwt
import requests
#creates the claim, 'secret' (from the private key), and the kid, from the service account file, and returns these values in a tuple.
#the tuple can then be used to make dependable positional argument entries to the parameters of the createJWT function.
def create_claim_from_json(self,objpath,scope=["https://www.googleapis.com/auth/admin.directory.user.readonly" "https://www.googleapis.com/auth/admin.directory.user"]):
with open(f'{objpath}','r') as jobj:
data = j.load(jobj)
claim = {
"iss": str(data['client_id']),
"sub": str(data['client_id']),
"scope": str(scope),
"exp": ((datetime.datetime.today() + datetime.timedelta(minutes=59)).timestamp()),
"iat": ((datetime.datetime.today()).timestamp()),
"aud": "https://oauth2.googleapis.com/token"
}
private_key = data['private_key']
kid = {"kid": f"{data['private_key_id']}"}
return claim, private_key, kid
#assembles the JWT using the claim, secret (Private key from the Service account file), the kid value, and the documented RS256 alg.
#returns the completed JWT object back to be used to send to the oauth2 endpoint
#the JWT will be used in the function call retrieve_oauth2token.
def createJWT(self, claim, secret, kid, alg='RS256'):
encoded_jwt = (jwt.encode(claim, secret, alg, kid)).decode('UTF-8')
return encoded_jwt
#Using the JWT created in memory, sends the JWT to the googleapi oauth2 uri and returns a token
def retrieve_oauth2token(self, jwt):
oauth2 = requests.post(f'https://oauth2.googleapis.com/token?grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant- type%3Ajwt-bearer&assertion={jwt}')
oauth2=oauth2.json()
return oauth2 #['access_token'], oauth2['token_type']
The documentation has a clear overview, did you follow the steps as described in the addendum? I am missing some parts of your code. But you did not mention using a service account (json) key. And the documentation also show that you have to use the (delegated) service account as both iss and sub. Furthermore, you need to use a kid. This is how it is done:
payload = {
'iss': '123456-compute#developer.gserviceaccount.com',
'sub': '123456-compute#developer.gserviceaccount.com',
'aud': 'https://firestore.googleapis.com/',
'iat': time.time(),
'exp': iat + 3600
}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers, algorithm='RS256')
url = "URL OF THE API TO CALL"
header = {'Authorization': f'Bearer {signed_jwt}'}
resp = requests.get(url, headers=header)
Note: you can find PRIVATE_KEY_FROM_JSON in the private_key_id field of your service account JSON credentials file.

Forbidden !! while trying to access the hereapi traces service

I've been working on here API from past one week, I've tested the geofencing and other rest services. I am trying to work on tracking, Where we have to generate a token by giving all the valid credentials. At last, I've got the token as well but when am trying to access the traces one for which the endpoint URL is
https://tracking.api.here.com/traces/v2/{trackingid}
here I've given the trackingid(deviceid) which I've used to generate an access token and included this token as a bearer in authorization I am using postman to test these, my token is valid for only 23 hours
Authorization Bearer {mytoken}
As mentioned I've also provided this x-request-id, I've no idea regarding this x-request-id but came to know about this from this thread and tried to generate uuid and use it for x-request-id
x-request-id 5506b7d0-2fe6-4967-8ad8-cf0f08fdedbf
And I am receiving the response as
{
"code": 403,
"id": "5506b7d0-2fe6-4967-8ad8-cf0f08fdedbf",
"message": "Forbidden",
"error": "Forbidden\n\nThe account does not have the correct
privileges\n"
}
The similar case even when I am trying to access the allotted geofences for that device and how many devices are in that particular geofence. I've read about whitelisting but whatever the service I am requesting for is not on their list. My account was a 90days free trial account
I am new to this hereapi Kindly correct me if I am doing anything wrong.
Kindly Help me out with this issue
Thanks in advance
--Meghana Goud
I've figured it out, I'll include the details here follow the step by step process as mentioned in the documentation
refer this HERE Tracking | API Reference
And follow the step by step process as mentioned in this documentation
The first one, you'll get your bearer token from this endpoint URL https://tracking.api.here.com/users/v2/login which is post
method and set its Content-Type to application/json and provide the username and password in JSON format and send a POST request to it
EndpointURL :https://tracking.api.here.com/users/v2/login
Headers :{"Content-Type":"application/json"}
Input :{"email":"XXXXXX", "password":"XXXX"}
Expected Response:{
"userId": "XXXXXX",
"accessToken": "XXXXX",
"tokenType": "bearer",
"expiresIn": 86399,
"refreshToken": "XXX"
}
the token is valid for only 24 hours. Now use this token for all the rest services you want to access from here-API
Now I would like to get the traces of my device using this endpointURL https://tracking.api.here.com/traces/v2/{trackingid}?count=1 , send a get request to this endpointURL by giving your trackingID, I repeat TrackingID is different from your deviceId TrackingId will be HERE-XXX(UUIDv4) whereas deviceId will be XXXX(UUIDv4)
now set the authorization to Bearer Token and pass an x-request-id which is a UUIDv4
Your request should look like
EndpointURL :https://tracking.api.here.com/traces/v2/{trackingid}?count=1
Headers :{"Authorization":"Bearer XXXXXX","x-request-id":"XXXX(UUIDv4)"}
Expected Response:{
"count": 1,
"data": [
{
"position": {
"lat": 17.44936354,
"lng": 78.36296417,
"accuracy": 45,
"alt": 539
},
"timestamp": 1531462419813,
"payload": {
"refAppData":
{
"batteryState": {
"charging": false,
"level": 52,
"temperature": 25
}
}
}
}
],
"pageToken": "1531462359711"
}
In order to update any data from your device, you'll require your device token which is generated from this endpoint URLhttps://tracking.api.here.com/v2/token you'll get your access token by OAuth1.o Authorization give the respected values as mentioned in the documentation. you'll get the response as
{
"accessToken": "XXXXXX",
"expiresIn": 86399
}
Similarly, you can test other services,
Hope this helps
Meghana