What is the simplest way to check if user is authenticated in Feathers hook without raising error? - feathersjs

This question was already answered here: Hook to check if user is authenticate in Feathers (without send Unauthorized error if not, just check)
But supplied answer does not work for all cases.
Looks like that in Feathers v4 there is no more allowUnauthenticated option, as it was in v3:
authenticate('jwt', {
allowUnauthenticated: true
})
But v4 anonymous authentication strategy does not work when you send an expired token.
If you configure hooks this way:
all: [ allowAnonymous(), authenticate('jwt', 'anonymous') ],
Anonymous strategy will not work if you send expired token and authenticate('jwt', 'anonymous') hook will respond with unauthorized error.

Related

RapidMiner : Can't get JWT Token

I am refering below document to get JWT Token .
However when I call the API /api/rest/tokenservice it doesn't return the token but returns a web interface asking for login . How can I get JWT Token
REST API Url :
https://docs.rapidminer.com/9.10/hub/rest-api/index.html
Response of postman:
In order to query the internal tokenservice endpoint, you need a valid "session". In the native installation method, you can use basic auth as "session" as outlined in the documentation.
curl -u user:pass "http://localhost:8080/api/rest/tokenservice"
{
"idToken": "the-valid-token",
"expirationDate": "the-exp"
}
However, for this to work when you've deployed RapidMiner AI Hub with Keycloak (and docker), you need to 1. enable basic auth for Keycloak, 2. access the route by first having a valid "login session" (cookie name is RM_SERVER_JSESSIONID) or 3. use a valid Keycloak token.
Enable basic auth in Keycloak
rm-server-homedir/configuration/keycloak/keycloak.json
{
...
"enable-basic-auth": true,
...
}
Valid cookie value
Login via web interface, open the browser's developer tools and use the very same RM_SERVER_JSESSIONID cookie value inside the REST request issued to the /api/rest/tokenservice endpoint.
Not sure what you like to achieve, e.g. schedule a process via REST, I like to outline that you can easily add a process and trigger via Web Service. The triggered process could make use of the Admin Tools extension. You still need to enable Keycloak's basic auth though if you like to trigger it from "outside". A guide how to use the extension can be found here.
Valid Keycloak token
Retrieve a valid Keycloak access token (from Keycloak's token endpoint, e.g. via OpenID Connect) and query the
/api/rest/tokenservice endpoint with Authorization: Bearer .
Disclaimer: This answer is used with permission of the original author from the RapidMiner community.

Should I treat an Expo Push Notifications Token as a sensitive information? If so, how do I send notifications in a secure way?

In my app, after a user sends a message to someone, another function is triggered to notify the receiver. For that, the sender has to have the receiver's push token (front end). My question is: Is that safe? Is there a better approach?
I'm using Firebase but I couldn't figure out a way to send this notification through Google Cloud Functions...
Yes you can treat it as sensitive information. Tokens could contain information that when a malicious user accessed, it can be used to impersonate your app and send their own messages to users. While there's no reported instance (yet), it would be wise to follow the best security practices.
According to this documentation on Sending Notifications with Expo's Push API
We offer the use of an access token alongside the push token as an additional layer of security.
If you're using the expo-server-sdk-node, upgrade to at least v3.6.0 and pass your accessToken as an option in the constructor. Otherwise, pass in the header 'Authorization': 'Bearer ${accessToken}' with any requests to our push API.
Any requests sent without a valid access token after you enable push security will result in an error with code: UNAUTHORIZED.
You can check this blog on Implementing Push Notifications with Expo and Firebase Cloud Functions on how to push notifications securely.

Cloud Schedule + Cloud Functions -> Gmail API watch() - WORKING NOW

This is my first post here. I am sorry if it's a repost, but I've been searching for more than one month for the answer to solve my problem in all websites and forums and until now... no answers!
My goal is to make a Gmail pub/sub watch() to make an action whenever I receive a new email.
To do so, according to the developer's website, I need to subscribe to Gmail watch() on a daily basis with the code:
request = {
'labelIds': ['INBOX'],
'topicName': 'projects/myproject/topics/mytopic'
}
gmail.users().watch(userId='me', body=request).execute()
Until now i have this a working scheduled task with a service account, with INVOKER Permissions. This part just works fine.
In my "initial autorization function" i have:
const {google} = require('googleapis');
// Retrieve OAuth2 config
const oauth2Client = new google.auth.OAuth2(
process.env.CLIENT_ID,
process.env.CLIENT_SECRET,
process.env.CALLBACK_URL
);
exports.oauth2init = (req, res) => {
// Define OAuth2 scopes
const scopes = [
'https://www.googleapis.com/auth/gmail.modify'
];
// Generate + redirect to OAuth2 consent form URL
const authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes,
//prompt: 'none'// Required in order to receive a refresh token every time
});
return res.redirect(authUrl);
};
My issue now is that the access token is generated via (prompt) the first time and never updates to a new one ( the token expires after 1hour...) it means this code stops working after that period and a "manual" intervention is required. According with the documentation, i need to use "offline" method and on "prompt" i can omit (only requests permissions on the 1st time) or none (never asks), like is said here.
I managed how to make it work! tomorow i will continue with the process.
Should i post here my working code for reference?
Thanks!
I will rephrase the process you illustrated so that there is no ambiguity.
According the documentation you pushed:
You do not suscribed to watch(), you call watch()
watch() is an API call to the Gmail API that will enable automatic events publication on a pub/sub topic you define given conditions you specified. Who are you watching? On what events?
You suscribe to a Pub/Sub topic that is targeted by your previous watch() call
A process (e.g: Google cloud function) suscribes to the topic and will consume messages sent by the Gmail API
The call is to be renewed at least every seven days
Because Google needs to be sure you still need to monitor the targeted inbox, it needs a renewal from you. Another watch() call will act so.
Cloud scheduler will enable this periodic renewal
this service will trigger your renewal script you put in your question. To do so it needs to be authenticated to the platform that host the script. It is easier if your script is hosted in a google service (cloud function, cloud run,...) and the authent type depends on the target URL form. In all cases YOU DO NEED an authent token in your request header. The token is generated from a service account you created with the right permission to call your script (e.g: cloud run invoker). By default the scheduler has the right to generate a token from it
So far so good. Now comes the tricky part and you don't mention it in your question. How is authenticated your gmail api client? You cannot monitor someone inbox, unless this person gave you the permission to i.e you call the API with the right Oauth2 token. Indeed in the video you point they authenticat the user using this principe which is implemented in their code with Express-oauth2-handler.
So you will have a cloud function to init end user authent and watch to his/her inbox. The renewal should do so but problem is user will not be there for accepting the end user consent. Here comes the offline access but it is beyond the scope of your question. Finally a second functions will suscribe to the pubsub topic and consume the message as you need. See their implementation code which populate a spreadsheet.
The documentation you shared in the comments does not say that you can remove the token from the headers of the service account, also the gmail API documentation you also shared says that you only:
need to grant publish privileges to gmail-api-push#system.gserviceaccount.com. You can do this using the Cloud Pub/Sub Developer Console permissions interface following the resource-level access control instructions.
In order to achieve this basically what you will need is a setup of two cloud functions, the first scheduled function is responsible for setting up the watch(), and you can check this documentation for how to deploy a scheduled function, and the second function being triggered by the pubsub of gmail notifications, you can check this documentation for how to build an event triggered function. Both processes are similar.
NOTE: I have never user the Gmail API, so I am not sure if any extra steps are necessary but then again, the documentation implies that setting up the permissions of that service account is enough to make it work.
EDIT:
As per the information you have shared. The issue is likely that you are not properly setting the Service Account to authenticate with the Cloud Function. As per described in the documentation, you have to grant to the Service Account the role Cloud Functions Invoker in IAM.
Let me know if this fixed the issue.

Pass Authentication Token to Service

I have used lifeary service builder to build my services. some of my services require that the user is authenticated before he can use them.
how can i generate an auth token and send it in the header or in the URL?
I have tried username#host.com:password#http://localhost:8080/PortletName-portlet/api/jsonws/?serviceClassName=com.service.NameServiceUtil&serviceMethodName=getMyNames&serviceParameters=[userid]&userid=1
and it did not work!
I have made sure i have added the below line in my portal-ext.properties and restarted the server.
json.service.auth.token.enabled=true
What more should i do to be able to pass Auth Token? is there a better method that i can use?
You actually want to use AuthVerifier. This is the best way how to access the Liferay API and be authenticated. It similar to the autologin concept.
Have a look at https://dev.liferay.com/es/discover/deployment/-/knowledge_base/7-0/authentication-verifiers and check out the PortalSessionAuthVerifier class in the source code.
The concept is quite simple. Read the request object and determine who the user is. Perform your custom authentication and return the auth result with the user identification.

Unable to login User ID to Web Messenger (Invalid Scope)

We're having issues initialising sessions in Smooch. We've successfully created a JWT token using the account level scope, and we've created a user (mycatalyst_test) using the API. When we use the API, we're able to access and query the user, create messages etc. correctly.
However, when we try to initialise the Smooch web messenger and log the user in:
Smooch.init({
appId: 'XXX',
userId: 'mycatalyst_test',
jwt: 'XXX',
embedded: true
});
We receive the error:
{"error":{"code":"forbidden","description":"Invalid scope"}}
We've checked the documentation and can't find any reference to the Invalid scope error or the Forbidden code in the Web Messenger documentation, and we're able to use the same JWT key to access the information through the API successfully, so we're not entirely sure what's going wrong.
We tried using the App scope rather than the Account scope to generate a new JWT key, but this also didn't work. We tried using the Smooch ID rather than the User ID, but this also didn't work.
We're at a bit of a loose end here, so would appreciate any pointers! (We're probably doing something stupid and obvious!).
See the documentation for authenticating users. When supplying a JWT to the login API, you must use a scope of appUser, otherwise you would be distributing JWTs to your users that give access to your whole account/app!
jwt.sign({
scope: 'appUser',
userId: userId
},
SECRET,
{
header: {
alg: 'HS256',
typ: 'JWT',
kid: KEY_ID
}
});
There is also this note in the authorization section of the REST API documentation:
An additional scope of appUser can also be used to authenticate users when using one of the Smooch native SDK integrations. For information on how and when to use this scope, see the guide for authenticating users.