Is it possible to make authorized calls to SFCC (demandware) OCAPI /shop using external customer authentication (e..g Cognito access token)? - authentication

Today, we use SFCC for e-commerce and it has also acted as our primary identity provider. We're in the process of migrating users and transitioning to use an external identity provider, Amazon Cognito.
After the migration, our hope was that we would be able to perform authentication using the external idp (Cognito) and use the issued Cognito 'Bearer' tokens to call the shop API.
Is this possible? Or, does the shop API require a JWT issued by SFCC?

I've not done it before, but there's a relatively new way to authenticate customers from a 'trusted system'. You can find more information about that here: https://documentation.b2c.commercecloud.salesforce.com/DOC2/index.jsp?topic=%2Fcom.demandware.dochelp%2FOCAPI%2Fcurrent%2Fusage%2FJWT.html
If your client application manages your customer credentials, it can obtain a JWT for a registered customer using the /customers/auth/trustedsystem resource. Because this API uses an OAuth token to identify the client application, we strongly recommend that you only use it in a system-to-system integration, where the client application keeps its own OAuth token secret.
After you are able to authenticate the customer you could use the Session Bridge functionality to convert that JWT to a session cookie.
Good luck!

Related

Can I federate Cognito with "client credentials" flow (or other way to trust a server-side application authenticated elsewhere?)

I have an AWS REST API Gateway with Cognito authentication using the client credentials grant.
We have been creating new clients by hand and sharing the ID/secret with people who need to use our API. They send the ID/secret and "grant_type=client_credentials" to Cognito, it gives them a bearer token and they use the API with the token. All fine so far. (It is a CLI tool running on a schedule, not accessed by a browser. I specifically need to avoid any sort of "go to the browser to login".)
Now, we have a new "island" of users who have a local OIDC (Azure AD) provider that can issue them a bearer token from a curl to an endpoint.
Is there a way to make Cognito accept those tokens??
I have tried federating Cognito with a different oidc provider (I don't have AD, but a different provider), getting myself a bearer token from it and sending it to the API GW, and I just get 401'ed. I don't know if there is something I'm doing wrong or if it's not possible.
(Things I might be doing wrong seems to be a long list! I need to create a client in the other provider and add it's ID/secret/URL to Cognito, that works. I used the same client ID/secret to generate my bearer token. But when I'm in client creds flow in Cognito, I need to set a custom scope. Do I need to add that scope to my initial request to the other provider (The API GW doesn't require a scope, it is just a mock endpoint at the moment in testing). The client_id= in the request is for the client in the other provider, not the Cognito client ID. Should I set it to the Cognito client ID?)
OR do I need to write a custom authenticator for the API GW to validate the token? (Decode JWT, Check : issuer is allowed and signature is valid.)
And not use Cognito at all for these other users.
(If it was an HTTP API, I think I can create a JWT authoriser and it does it all for me, but it isn't and there are some features on REST APIs not available on HTTP (like WAF))
Sorry it's a bit short on details. I could spend days copy/pasting all the configs from ID provider/Cognito but if it fundamentally won't work I wasted my time!
(After trying it, I think maybe federation only works for actual users with a browser based login flow, not clients with a CLI flow. I can't find anyone saying client credentials flow does work anyway!)
Cognito is using the authorization server role. So in all cases, the tokens returned to client applications will be issued by Cognito. These apps will never deal with Azure AD tokens. Multiple types of client can coexist together:
CLIENT CREDENTIALS GRANT
Clients who use this flow might represent B2B connections. The business partner must always get Cognito tokens directly, and no federation is used here.
AUTHORIZATION CODE GRANT
Browser clients will use this flow, and you can configure Cognito to implement authentication by making a second OIDC Connect redirect to Azure AD.
My blog post provides a walkthrough on how settings are configured. Cognito will act as a client of Azure AD and use a scope such as openid profile email.
After a user login, Cognito will receive Azure AD tokens, validate them, then issue its own tokens. Nothing will change in the API gateway, which will continue to verify Cognito tokens.

How do I use Google's Identify Platform to authenticate against Cloud Endpoints?

In our organisation we use the Google Kubernetes Engine (GKE) to implement a micro-service architecture. As we are also G-Suite users, everyone in the organisation is guaranteed to have a Google account. In consequence we would like to use those accounts to manage authentication and authorization of micro services.
We have prototyped login using the angularfire2 client to authenticate against the Google Identity Platform. We also have Google Cloud Endpoints configured to control access to relevant services.
The piece we are missing is how to get from the identity in Google to an access token we can use on our services -- the access token coming back using the Firebase API has no claims in it, and the documentation on custom claims seems to make it quite clear that these go into the identity token.
My expectation would be to have JWTs with the appropriate audience (our backend), containing a sufficient set of claims to implement role based access control within the services. Ideally the infrastructure could validate a claim already -- some of our services are small enough to require only one role, which could be enforced outside the service. Or we could annotate our endpoints (Protobuf) with the required claims.
In the GCP environment, what is the standard process of creating access tokens to be used for accessing GKE services? Is there anything that supports this?
The piece we are missing is how to get from the identity in Google to
an access token we can use on our services -- the access token coming
back using the Firebase API has no claims in it, and the documentation
on custom claims seems to make it quite clear that these go into the
identity token.
Google OAuth Access Tokens do not have an identity in the sense that you want to use it. Identity is stored in the Identity Token. Add the scope "email" when authenticating the user. Google will return an ID Token. For some frameworks, you can request custom claims for the Identity Token.
In the GCP environment, what is the standard process of creating
access tokens to be used for accessing GKE services? Is there anything
that supports this?
There are two types of access excluding methods such as API keys. User Accounts and Service Accounts. Service-to-service typically uses service account Access Tokens (RBAC) or service account Identity Tokens (IBAC). In your case, you want to use Identity Platform which means User Accounts.
If I was designing this system, I would use User Accounts to authenticate with the system - Firebase is great for this purpose. I would look up what roles this identity supports/allows from my database (Firestore) and create a service account Access Token with the required scopes for GCP services. I would then use this Access Token for GCP service-to-service authorization. If I also required custom roles for my own services, I would create a custom Identity Token with my custom roles and include that as a custom HTTP header and include the Google Access Token in the standard HTTP "authorization: bearer" header. I would use the service account private key to sign my custom Identity Token or use a GCP IAM API to sign for me so that the other end can verify with the service account's public key. This method prevents data leakage at the client, no private keys are distributed, scopes/roles are not disclosed, etc.
I would suggest you follow this doc of authentication between services by using service account files.

Authentication using SAML

My client asked me to develop a web api and use SAML as authentication.
I came across with the image below from this site, that shows the authentication flow.
However I don't know how to use the token that is generated after the authentication.
Do I need to store it as any other session variable?
Do I have to renew the token after a certain time or it lasts during all the session?
Note: The authorization server / idP is maintained by other party.
Since you develop the web API yourself, there's no need to refresh the token.
You're API needs to be added as relying party to the IdP. After that you can redirect to the IdP and initiate authentication. The token you get back contains several attributes (also configurable on the IdP) like unique user-id (uid), e-mail, name, country, etc...
In most cases this token is signed using a public/private key. Your API server needs to verify the signature, the issuer (the IdP), the audience (your API) of the token and consume the attributes. When everything is OK, you'll need to provision a local user account, link the external uid and create a local authentication cookie (or generate a OAuth2 token if your API uses OAUth2 or OpenIdConnect) for the locally provisioned user account.
Since this is a complex process, depending on the language/framework you're using, you might want to look into existing implementations.

How to use oauth with 1st party client-side js app?

The model for our product is like this:
Api backend (headless)
I already have oauth set up and ready to use with a resource owner credentials grant. Anyone who wants to use our api can do so using either an API key or their username/password. Of course they also need their client ID and secret.
SPA frontend that accesses the Api
I have built an SPA that will uses the api to provide a portal GUI for our clients. Given that this client-side app is owned and administrated by us (so it's a trusted app) how can I safely authenticate users using only username/password with oauth?
Originally it was using a JWT auth system that only required username/pass but now that we've implemented oauth I'd like to consolidate. It's unreasonable to make every user need to also have their client id and secret on hand to login, but I want users to have full access to the api from the GUI.
I've looking at using CSRF tokens but how would that work with my app when nothing is generated server-side?
I'm not sure how to proceed.
EDIT: very similar to the problem here.
I have decided to use the solution described here.
And here is a snippet of my implementation
The TL;DR version is
Create a proxy between the app and the api
Store the client ID and secret in the proxy
App logs in using password grant type -- proxy intercepts login request and inserts client id and secret
On login response proxy returns access token as an encrypted cookie
Client stores cookie and sends with api requests (to proxy)
Proxy decrypts cookie and inserts access token into Authorization header before forwarding to api endpoint
For me this has several advantages over implementing something custom on the api itself:
No need for custom grant on oauth server
ID/secret is hidden from app securely and can still use password grant
oauth server can identify client (no need for separate client ids for each user)
You should not use the resource owner credential grant from a JavaScript application. The fact that you own and administer the application does not make it a trusted application.
A trusted client is an application that can keep a secret. SPAs or any JavaScript app cannot keep a secret.
You should use the implicit grant for non-trusted clients.

restful api authentication confusion with oauth2

I did some investigation about restful api authentication. Most people pointed to Oauth2 for restful api authentication. I looked into some of resouces, especially this link https://developers.google.com/accounts/docs/OAuth2.
It seems to me Oauth2 is for a third party app to access users' data in google/facebook(or other data provider).
Our problem is that we own the data, we don't need to access our client's any third party data and our clients don't have to any third party data. We want to protect our api with some sort of authentication.
For our case what is the convenient technologies for our restful api authentication ? We will expose our api like this
https://ourdomain.com/api/<endpoint>
Our clients can access a website first to register https://ourdomain.com and they should be able to get clientId and clientKey from our website for accessing apis. Our clients should be able to consume through some sort of authentication
In oAuth 2.0, there are several types of grant types. A grant type is just a way to exchange some sort of credentials for an access token. Typically oAuth refers to 3rd party usage with a Authorization Code Grant. This means redirecting the user to the resource owner's website for authentication, which will return back an Authorization Code.
This clearly doesn't make sense for 1st party oAuth use, since you ARE the resource owner. oAuth 2.0 has considered this and included the Resource Owner Password Credentials Grant for this purpose. In this case, you can exchange a username and password for an access token at the first party level.
See https://www.rfc-editor.org/rfc/rfc6749#section-4.3 for more details.
If I understand correctly, what you need it similar to OAuth in a way that you do the exact same thing minus granting a 3rd party app access to a user's resources.
In OAuth, there is a central system that manages authentication and authorization by checking an app's credentials + user's credentials and dishing out authorization tokens. There are multiple endpoints that will accept these authorization tokens.
The tokens are basically encrypted strings that contain info about the user's credentials and some other info that might be needed by your app.
What you need (i believe) is a similar authentication endpoint, that the client hits with its credentials and gets a token.
So,
i) Create a registration form/console where a client can register and get his credentials. Have a look at this.
ii) Define a HTTP endpoint where the user exchanges his credentials for an access token + refresh token.
iii) The client can hit the resource endpoint with the access tokens to make authenticated calls to any of your endpoint.
iv) At the back-end you'd need a common service that verifies the tokens and extracts info from it.
PS - This is just a minimal system, there would be a lot of security considerations like what if some unauthorized app gets access to some client's access tokens.
You can find much information about CSRF attacks, noonces, timestamps and other methods of mitigating security concerns.
Just to be clear with the original question:
OAuth2 needs at least a client and a server
OP was wondering how to secure a REST API, and why everyone is talking about third party authentication providers (Google, Facebook, ...)
There are 2 different needs here:
1 - Being able to secure a personal API (ourdomain.com)
Client Server
Consumers <----> Your API
2 - Being able to consume a public API (For example getting a user's Google contact list)
Client Server
You <----> Google APIs
OP actually needs the 1st: implement an OAuth2 server in front of its own API.
There are many existing implementations for all languages/frameworks on Github
Finally, here is one nice Oauth2 technical explanation, and I'm shamelessly taking one of its schemas here:
No I'm not working at Google, I'm just taking Google as a public API supplier example.