bigCommerce customer api - Customer JWT for sso - bigcommerce

In my app (node-bigcommerce-sdk) my customers will need to login as if they were on the bc store. I am able to verify that the provided email and password are correct. I cant find a method to exchange the user_id and my app credentials for a token that can be used in sso (described here)
I used the python sdk before and the part I want to do now in nodejs is the following
bc_client = b.api.BigcommerceApi(client_id, store_hash, access_token)
login_token = sdk.customer_login_token.create(bc_client, customer.id)
so far (not working)
let token = jwt.encode({
"iss": account.clientId,
"iat": 123456789,
"jti": "uid-"+uid,
"operation": "customer_login",
"store_hash": account.storeHash,
"customer_id": uid,
}, account.secret, 'HS512');
let sso_url = `${account.entry_url}/login/token/${token}`
example token received
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJja244ZzN5Z3V4MmY0cG14ZWw0M2dqbmJjOTViZ2FrIiwiaWF0IjoxMjM0NTY3ODksImp0aSI6InVpZC0xIiwib3BlcmF0aW9uIjoiY3VzdG9tZXJfbG9naW4iLCJzdG9yZV9oYXNoIjoiMmJpaHByMnd2eiIsImN1c3RvbWVyX2lkIjoiMSJ9.n4lygAJtfqhcrHnGEWle1far-Ee69xrgym-HWFWWwNWXB1-hBziKC03SK_y8PYjLBL_n43Q6K07YH9ysSV5a4g
${account.entry_url}/login/token/${token} results in an error message on the frontend Invalid login. Please attempt to log in again.

Related

"error": "unauthorized_client", "error_description": "AADSTS700016 (Microsoft Graph API)

I want to access my todo list using Microsoft graph API and so registered an app and after doing the required steps got the access token, but after trying to get the new access token using the refresh token it returns this message: "error": "unauthorized_client", "error_description": "AADSTS700016: Application with identifier 'id' was not found in the directory 'Microsoft Accounts'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant
class Refresh:
def __init__(self):
self.refresh_token = refresh_token
self.scope = scope
self.client_secret = client_secret
def refresh(self):
query = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
response = requests.post(query,
data={"client_id" : client_id,
"scope": 'Tasks.Read%20Tasks.Read.Shared%20Tasks.ReadWrite%20Tasks.ReadWrite.Shared%20offline_access',
"refresh_token": refresh_token,
"redirect_uri": 'https://github.com/Rohith-JN',
"grant_type": "refresh_token",
"client_secret": client_secret
},
headers={"Content-Type": "application/x-www-form-urlencoded"})
response_json = response.json()
print(response)
print(response_json)
a = Refresh()
a.refresh()
I am also not sure if I am entering the scopes in the right way. Any help would be really appreciated
I finally figured it out by changing the URL that refreshes the token from
https://login.microsoftonline.com/common/oauth2/v2.0/token to this https://login.microsoftonline.com/{tenant_id}/oauth2/token

ERPNext: How can I generate user session without Password?

As an ERPNext fresher, I am creating a REST API for the mobile app, where the use case is, the Mobile user will send a request to do login using Face authentication, as a result of Face authentication at the mobile end, it will return User ID(same as ERPNext UserID).
As a Param, I will get UserID and other params of API request, here in response, I have to send a new session generated for that User.
Applied solution:
Tried Login by fetching password of user based on UserID, which basically gives encryption error for encrypted password.
Tried bypass login and generate new session, failed due to password not being added
Decrypt the password to use as param for new session
My current problem is, I don't have Password in normal format, and need to generate a valid user session, for the next operation post face recognization(face validation is already done through SDK).
You can use token based authentication for REST Api, based on your question when you receive emailid (same as erpnext user id), you can identify the user and generate api_key and api_secret, you can return these keys in response to your request, also you can store these secrets keys and use for future requests to authenticate it
You can refer docs here https://frappeframework.com/docs/user/en/api/rest#1-token-based-authentication
Below is sample code, please note code is not tested, posted just for reference
#frappe.whitelist(allow_guest=True)
def validate_user(email):
user_email = frappe.db.get_all('User', filters={'name': email}, fields=['name'])
user = frappe.get_doc('User', user_email[0]['name'])
api_generate = generate_keys(user.name)
user_resp = frappe.get_doc('User', user.name)
frappe.response["message"] = {
"status": 1,
"message": "Authentication success",
"api_key": user_resp.api_key,
"api_secret": api_generate,
"username": user.username,
"email": user_resp.email,
"role": user_resp.roles[0].role
}
def generate_keys(user):
user_details = frappe.get_doc('User', user)
api_secret = frappe.generate_hash(length=15)
if not user_details.api_key:
api_key = frappe.generate_hash(length=15)
user_details.api_key = api_key
frappe.db.set_value('User', user, 'api_secret', api_secret)
return api_secret

Android publisher permission Denied only check payment(other api successfully)

I'm trying to call api Purchases.products: get to verify your purchase
it yields such a result
{
"error": {
"errors": [
{
"domain": "androidpublisher",
"reason": "permissionDenied",
"message": "The current user has insufficient permissions to perform the requested operation."
}
],
"code": 401,
"message": "The current user has insufficient permissions to perform the requested operation."
}
}
the project is tied properly
A new service account with owner rights has been created
This service account has been granted rights in the google play console
Documentation here says what you can do
the received token does not work only for purchase checks for any other api it returns the result(Inappproducts: list is work)
The verification url is built right because if you get a token client to server then this api works too - but I need a server to server auth
scopes = ['https://www.googleapis.com/auth/androidpublisher']
authorization = Google::Auth.get_application_default(scopes)
uri = "https://www.googleapis.com/androidpublisher/v3/applications/#{ENV['ANDROID_PACKAGE_NAME']}/purchases/products/#{purchasable.purchase_uuid}/tokens/#{purchase_token}?access_token=#{authorization.fetch_access_token!['access_token']}"
response = RestClient::Request.execute method: :get,
url: uri,
headers: {'Content-Type':'application/json'}
and
file = File.read('config/google_key.json')
values = JSON.parse(file)
oauth = Signet::OAuth2::Client.new(
issuer: values[:client_email]",
audience: "https://www.googleapis.com/oauth2/v4/token",
scope: "https://www.googleapis.com/auth/androidpublisher",
client_id: values[:client_id],
signing_key: OpenSSL::PKey::RSA.new(values[:private_key]),
)
jwt = oauth.to_jwt
url = "https://www.googleapis.com/oauth2/v4/token"
begin
response = RestClient::Request.execute method: :post,
url: url,
headers: {'Content-Type': 'application/json'},
payload: {
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: jwt
}
result = JSON.parse response.body
rescue => e
puts e.response.to_str
result = JSON.parse(e.response.to_s)
end
I expect this result
update 1
add tokeninfo
I love google.
after 7 days with my first service account it worked - but 7 days !!!! 7 days !!!! it's just horror
Guys in Google you need 7 days to give access to api!! - this is ridiculous
Okay, you need to do this to get access
create service account in google cloud (admin rights)
create google play console and link project google cloud
add email service account in google play console
after 1 week it will work

BigCommerce StoreFront API SSO - Invalid login. Please attempt to log in again

Been at this for a few days. I am making a login form on my angular/nodejs app. The bc-api is able to verify the user/password. Now with that i need to allow the customer to enter the store with sso but the generated jwt is not working. My attempt below... I am looking for troubleshooting tips.
Generate JWT / sso_url
var jwt = require('jwt-simple');
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
function get_token(req, data) {
let uid = req.id;
let time = Math.round((new Date()).getTime() / 1000);
let payload = {
"iss": app.clientId,
// "iat": Math.floor(new Date() / 1000),
"iat": time,
"jti": uid+"-"+time,
"operation": "customer_login",
"store_hash": app.storeHash,
"customer_id": uid,
"redirect_to": app.entry_url
}
let token = jwt.encode(payload, app.secret, 'HS512');
token = decode_utf8(token);
let sso_url = {sso_url: `${app.entry_url}/login/token/${token}`}
return sso_url
}
payload resolves to
{
"iss": "hm6ntr11uikz****l3j2o662eurac9w",
"iat": 1529512418,
"jti": "1-1529512418",
"operation": "customer_login",
"store_hash": "2bihpr2wvz",
"customer_id": "1",
"redirect_to": "https://store-2bihpr2wvz.mybigcommerce.com"
}
generated sso_url
https://store-2bihpr2wvz.mybigcommerce.com/login/token/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJobTZudHIxMXVpa3oxMXpkbDNqMm82NjJldXJhYzl3IiwiaWF0IjoxNTI5NTEyNDE4LCJqdGkiOiIxLTE1Mjk1MTI0MTgiLCJvcGVyYXRpb24iOiJjdXN0b21lcl9sb2dpbiIsInN0b3JlX2hhc2giOiIyYmlocHIyd3Z6IiwiY3VzdG9tZXJfaWQiOiIxIiwicmVkaXJlY3RfdG8iOiJodHRwczovL3N0b3JlLTJiaWhwcjJ3dnoubXliaWdjb21tZXJjZS5jb20ifQ.vaeVTw4NjvX6AAPChgdXgMhm9b1W5B2QEwi4sJ6jz9KsKalqTqleijjRKs8jZP8jdQxC4ofYX5W0wYPMTquxQQ
result
about my env
I am using nodejs express... my bc app's secret & clientId are being used above and they work for several other bc-api tasks. My app is installed and authenticated on bc admin. The app being used to do the above is running on localhost but i also tried online https (same result).
I am thinking that there might be some incorrect configuration in my stores admin but havent found anything to change.
I decoded your JWT on jwt.io and I get this:
Header:
{
"typ": "JWT",
"alg": "HS512"
}
There's at least one problem here
BC requires HS256 as the algorithm according to docs
https://developer.bigcommerce.com/api/v3/storefront.html#/introduction/customer-login-api
Body:
{
"iss": "hm6ntr11uikz11zdl3j2o662eurac9w",
"iat": 1529512418,
"jti": "1-1529512418",
"operation": "customer_login",
"store_hash": "2bihpr2wvz",
"customer_id": "1",
"redirect_to": "https://store-2bihpr2wvz.mybigcommerce.com"
}
Problems here:
JTI should be a totally random string, using something containing the time could result in duplicates which will be rejected. Try using a UUID
Customer ID should be an int, not a string
The redirect_to parameter accepts relative URLs only. So try "redirect_to": "/" if your goal is to redirect to the home page.
Another potential problem is system time - if your JWT was created in the "future" according to BC's server time, your JWT also won't work. You can use the /v2/time endpoint response to specify the IAT, or to keep your own clock in sync.

Linkedin token not valid

Here is a strange thing I am fighting against.
First of all I am using this simple-linkedinphp lib to perform API calls from my php backend.
I got a user access token from our IOS app which has the following structure:
{"access_token":"lettersAndSymbols","expires_in":5183999}
I store it in a variable called $token.
Then I try to get the user's profile with this token like this:
$linkedin = new \LinkedIn($this->linkedin_config);
$linkedin->setResponseFormat($linkedin::_RESPONSE_JSON);
$linkedin->setTokenAccess(array('oauth_token' => $token["access_token"], 'oauth_token_secret' => ""));
$linkedinUserJson = $linkedin->profile("~");
Then I get the response with error:
array(5) {
["linkedin"]=>
string(358) "{
"errorCode": 0,
"message": "[unauthorized]. The token used in the OAuth request is not valid. sameLettersAndSymbols",
"requestId": "74T6SY6ML6",
"status": 401,
"timestamp": 1376043937705
}
But when I try to open an api url in a browser with the same LettersAndSymbols like https://api.linkedin.com/v1/people/~?oauth2_access_token=LettersAndSymbols, I get the correct response with user object.
How can that be? Am I doing something wrong with the API lib?
I can see a problem in this line
$linkedin->setTokenAccess(array('oauth_token' => $token["access_token"], 'oauth_token_secret' => ""));
your must provide a secret to set the token access.
I found a nice example about Linkedin Integration, wich I like to share with you, I tested and it works just fine.
How to Integrate login with LinkedIn oAuth in PHP