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

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.

Related

Unable to set scopes with EnableTokenAcquisitionToCallDownstreamApi with AddMicrosoftIdentityWebApiAuthentication

This compiles in startup.cs:
string[] initialScopes = Configuration.GetValue<string>("GraphApi:Scopes")?.Split(' ');
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph();
However, since I'm working on an API controller only, and not a web app, I want to do this instead:
string[] initialScopes = Configuration.GetValue<string>("GraphApi:Scopes")?.Split(' ');
services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph();
However, this does not compile. At least not with Microsoft.Identity.Web v1.0. Intellisense tells me that string[] is not assignable to parameter type ConfidentialClientApplicationOptions.
The difference is that AddMicrosoftIdentityWebApiAuthentication returns a MicrosoftIdentityWebApiAuthenticationBuilder whereas the former returns a `MicrosoftIdentityAppCallsWebApiAuthenticationBuilder.
Is there a work-around here?
What I'm trying to accomplish, is to ensure that the scope is set correctly when the Graph access token is requested. Currently, this does not seem to be the case, as I get an error like this when trying call Graph - e.g. await graphServiceClient.Applications.Request().GetAsync();.
---> Microsoft.Identity.Web.MicrosoftIdentityWebChallengeUserException: IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
---> MSAL.NetCore.4.18.0.0.MsalUiRequiredException:
ErrorCode: user_null
Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was
In other words, what I need is an application access token which looks like this:
[...more json]
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/{tenant id}/",
"iat": 1602055659,
"nbf": 1602055659,
"exp": 1602059559,
"aio": "[...]",
"app_displayname": "My app",
"appid": "{App id guid}",
"appidacr": "1",
"idp": "https://sts.windows.net/{tenant id}/",
"idtyp": "app",
"oid": "{guid}",
"rh": "[...]",
"roles": [
"Application.ReadWrite.All",
"Directory.ReadWrite.All",
"Directory.Read.All",
"Application.Read.All"
],
"sub": "{guid}",
"tenant_region_scope": "EU",
"tid": "{tenant id}",
"uti": "[...]",
"ver": "1.0",
"xms_tcdt": 1597308440
}.[Signature]
I can generate the above manually with Postman and if I use it, it works. Confirming that the configuration of the Application is correct in Azure AD.
Apparently, using an application access token is current not yet supported.
IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user #667
use
.AddMicrosoftGraph(Configuration.GetSection("GraphAPI"))
and make sure you appsettings.json contains the following (use the Scope you want separated by space):
"GraphAPI": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read mail.read",
"DefaultScope": "https://graph.microsoft.com/.default"
}

Parse: no sessionToken retrieved after initial sign up using Google oAuth

For my React Native app I am using Parse JS SDK and hosted Parse Server on Back4app.
When I try to register a new user, the user is not authenticated because the response does not return a sessionToken.
However, once the user is in the db and signs in a sessionToken is returned and the user is authenticated successfully.
Request
The request is the same for sign in/up.
await Parse.User.logInWith('google', {
// auth data received from #react-native-community/google-signin
authData: {
id,
id_token: token
}
})
Response on initial Sign Up
The response is supposed to return a sessionToken which is missing. So the user is not authenticated and modifications on the user object are not possible.
{
"authData": {...},
"createdAt": "...",
"objectId": "...",
"updatedAt": "...",
"username": "..."
}
Response on sign in after user was created
{
"ACL": {...},
"authData": {...},
"createdAt": "...",
"objectId": "...",
"sessionToken": "...",
"updatedAt": "...",
"username": "..."
}
I don't use any cloud code. Just a simple auth flow with Google oAuth.
Any help is highly appreciated.
Edit: same issue for 'sign in with Apple'
As far as I know, according to the Official Documentation, Parse will respond 200 (HTTP OK) and include the Session Token only when it verifies the user is already associated with the OAuth authentication data.
So, again, as far as I know, the very first request when you create the user, will not contain the sessionToken.
Take a look to this tutorial https://www.thinkertwin.com/how-to-setup-google-oauth2-login-with-parse-server-in-react/
Here there is an explanation on how to setup your Cloud Code. It's for React, but with small adjustments it will work for React Native.
You also need Cloud Code as you need to store your Client ID and Secret. You don't want to have those on your public application

bigCommerce customer api - Customer JWT for sso

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.

Create MasterCard tokenization API

I have a mobile app containing payment method via MasterCard. I have this tutorial:
https://ap-gateway.mastercard.com/api/documentation/apiDocumentation/rest-json/version/latest/api.html?locale=en_US
I want to create Tokenization which contains customer's master detail, I have followed this tutorial part:
https://ap-gateway.mastercard.com/api/documentation/apiDocumentation/rest-json/version/latest/operation/Tokenization%3a Create or Update Token (with system-generated token).html?locale=en_US
I tried with :
POST https://ap-gateway.mastercard.com/api/rest/version/41/merchant/{{MyMerchantID}}/token
Params:
{
"sourceOfFunds": {
"type": "CARD",
"provided": {
"card":{
"number": "5123450000000008",
"expiry": {
"month": "05",
"year": "17"
}
}
}
Note: The number is a mastercard test number.
I am always get this error:
error
cause "INVALID_REQUEST"
explanation "Invalid credentials."
result "ERROR"
I followed the params in second URL.
Can anyone help? Are the params correct or I missed something?
In your configuration file, you need to set the following:
$configArray["merchantId"] = "[merchantId]";
// API username in the format below where Merchant ID is the same as above
$configArray["apiUsername"] = "merchant.[merchantId]";
// API password which can be configured in Merchant Administration
$configArray["password"] = "your api password";
Setting the above parameters in the config file will solve your problem
Try replacing "ap-gateway" with the real gateway provided for you. Your merchantID is not supported in test gateway.
First, you should ask you bank to enable the tokenization for your merchant account
POST
https://ap-gateway.mastercard.com/api/rest/version/61/merchant/{{MyMerchantID}}/token
you have to set Authorization->Basic Auth
Username : Your_MerchantID
Password : ApiPassword
Params:
{
"session": {
"id": "SESSION0002510583427E2239608H32"
}
}

Can chrome.identity.launchWebAuthFlow be used to authenticate against Google APIs?

I'm writing a Chrome extension and have been trying to use chrome.identity.launchWebAuthFlow to authenticate with Google. I would prefer this to chrome.identity.getAuthToken (which does work) because getAuthToken gets the token for the user currently logged in to Chrome -- who may be logged in to multiple Google accounts. I want the user to be able to hook up a specific Google calendar to my extension, and that calendar might belong to a different user than they've logged in to Chrome as.
So, I've been trying to do this with chrome.identity.launchWebAuthFlow and generally failing around a mismatched redirect_uri. I've tried just about every type of credential you can set up in the Google APIs developer console. ("Chrome App" seemed like the right thing, but I have also tried Web application, Other, and iOS.) I've tried using the results of both chrome.extension.getURL('string') and chrome.app.getRedirectURL('string') as my redirect_uri.
I tried out the example app referred to by https://stackoverflow.com/questions/40384255/oauth2-angular-chrome-extension but have not been able to get that to work either.
I have a suspicion I'm trying to do something that either used to be allowed and no longer is, or just never worked.
Here's an example of my code, but I think my problem is really in the API dev console -- I don't see a way to set up a configuration that will work for an extension:
var auth_url = 'https://accounts.google.com/o/oauth2/v2/auth';
var client_key = *[client id from API dev console]*
var auth_params = {
client_id: client_key,
redirect_uri: chrome.identity.getRedirectURL("oauth2.html")
scope: 'https://www.googleapis.com/auth/calendar'
};
auth_url += '?' + $.param(auth_params);
chrome.identity.launchWebAuthFlow({url: auth_url, interactive: true}, function(token) { console.log(token); });
(I have also tried the https://accounts.google.com/o/oauth2/auth endpoint.)
Solution:
After reading the accepted answer, I wound up with this:
var auth_url = 'https://accounts.google.com/o/oauth2/auth';
var client_id = '[client ID from console]';
var redirect_url = chrome.identity.getRedirectURL("oauth2.html");
var auth_params = {
client_id: client_id,
redirect_uri: redirect_url,
response_type: 'token',
scope: 'profile'
};
auth_url += '?' + $.param(auth_params);
console.log(auth_url);
chrome.identity.launchWebAuthFlow({url: auth_url, interactive: true}, function(responseUrl) { console.log(responseUrl); });
The responseUrl is my redirect_uri with parameters -- so Google oauth returned that instead of redirecting the browser to it -- and I could go on from there.
Yes, in 2019 it still works. Finally got it working...
manifest.json
{
"name": "Extension Name",
"description": "Description",
"version": "1.0.0",
"manifest_version": 2,
"icons": {
"48": "icons/icon_48.png",
"128": "icons/icon_128.png"
},
"background": {
"scripts": [
"background.js"
],
"persistent": false
},
"oauth2": {
"client_id": "Your Client ID from Google Develpers console (Must be Web Application)",
"scopes": [
"openid", "email", "profile"
]
},
"permissions": [
"identity"
],
"key": "Your Key from Google Developer Dashboard"
}
background.js
chrome.windows.create({
'url': './content/auth/auth.html',
'width': 454,
'height': 540,
'type': 'popup'
});
auth.html
standard HTML markup that calls auth.js file
auth.js
var auth_url = 'https://accounts.google.com/o/oauth2/auth?';
var client_id = '<Client ID>'; // must be Web Application type
var redirect_url = chrome.identity.getRedirectURL(); // make sure to define Authorised redirect URIs in the Google Console such as https://<-your-extension-ID->.chromiumapp.org/
var auth_params = {
client_id: client_id,
redirect_uri: redirect_url,
response_type: 'token',
scope: 'https://mail.google.com/',
login_hint: 'real_email#gmail.com' // fake or non-existent won't work
};
const url = new URLSearchParams(Object.entries(auth_params));
url.toString();
auth_url += url;
chrome.identity.launchWebAuthFlow({url: auth_url, interactive: true}, function(responseUrl) {
console.log(responseUrl);
});
To get the Angular sample running, I needed to:
Create my own Web Application client ID in the Google developer console with an Authorized redirect URI of https://bcgajjfnjjgadphgiodlifoaclnemcbk.chromiumapp.org/oauth2
Copy that client ID into the config.json file of the sample.
The call to get redirectURI in that sample is like chrome.identity.getRedirectURL("oauth2"), the string parameter gets appended to the end of the URL based on extension ID.