Twitter OAuth Strategy Access Level & Email Problem - node.js

I have a Twitter OAuth strategy like this:
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
userProfileURL: "https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true",
requestTokenURL: 'https://api.twitter.com/oauth/request_token?x_auth_access_type=read',
callbackURL: '/dashboard/auth/callback',
proxy: true
Now, here whenever I include requestTokenURL: 'https://api.twitter.com/oauth/request_token?x_auth_access_type=read', I am not able to access the user's email. If I remove it, I am able to access the email via userProfileURL: "https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true".
I have enabled the request email permission in the developer dashboard. What am I missing? I am using the passport-twitter library for this.

Unfortunately this does not seem possible.
Unfortunately the initial x_auth_access_type setting was created at a point long before the email permission was added, and has only ever allowed one or other of the read or write values to be specified. I think what you’re seeing here is that using that parameter does perform an absolute override on what you have configured on the app settings. I’ll note this as something we should improve in the future, but at the moment I can’t say when or if we’re likely to change that behaviour.
Source: https://twittercommunity.com/t/email-is-not-requested-when-x-auth-access-type-parameter-added/72396/5

Related

How can I allow users to join Google Meet without having to ask?

I'm scheduling a google meet based on specific time and date, and so far it's going well, it generates a google meet link. But the only problem is that I have to ask to join while no one is there to accept. Is there is a way to get around this? knowing that I get the emails of both of the participants.
I'm using a package called google-meet-api
This is the code:
const meetingLink = await Meeting({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN,
date,
time,
summary: 'Interview',
location: 'Online',
description: 'Interview',
});
if (!meetingLink) {
throw new CustomError('Error creating the meeting, please try again later', 500);
}
console.log(meetingLink) // https://meet.google.com/arr-yrre-t**
If you're the primary user or one of the invitees, then the URL should give you the option to "join the meeting" even if noone else (including the organizer) is present.
Without more details in your question, it's difficult to provide more help.
Are you using this NPM package: google-meet-api?
The NPM package is an implementation of the Google SDK method and is little more than the example code that's provided by Google.
I encourage you to consider writing this code for yourself and saving yourself a mostly redundant depdendency on a 3rd-party NPM package that adds very little value.
The Google documentation page for the calendar Events:insert method (which is what is being used by the google-meet-api package) provides details of the parameters and the request body.
By reviewing the parameters and request body fields, you can confirm to yourself whether you're missing one of the fields that would address your problem.

How can I protect the loopback explorer by username and password?

I've just started using loopback4 and I would like to protect the /explorer from being public. The user would initially see a page where username and password must be entered. If successful, the user is redirected to /explorer where he can see all API methods (and execute them). If user is not authenticated, accessing the path /explorer would give a response of "Unauthorized". Is there a way to easily implement this?
There is issue talking about a GLOBAL default strategy is enabled for all routes including explorer in https://github.com/strongloop/loopback-next/issues/5758
The way is to specify a global metadata through the options:
this.configure(AuthenticationBindings.COMPONENT).to({
defaultMetadata: {
strategy: 'JWTStrategy'
}
})
this.component(AuthenticationComponent);
registerAuthenticationStrategy(this, JWTAuthenticationStrategy)
But in terms of enabling a single endpoint added by route.get(), it's not supported yet, see code of how explorer is registered. #loopback/authentication retrieves auth strategy name from a controller class or its members, but if the route is not defined in the controller, it can only fall back to the default options, see implementation

Chrome extension Oauth2 authentication and verification issue

I am developing chrome extension that uses several google API services. I've set up Oauth2 working code and authentication process works fine. However, I am getting "unverified app" screen and would like to get rid of that.
So, I went through google's verification process several times and I keep getting declined with explanation that I need to verify domain ownership of chromiumapp.org - which is I don't understand. Here's why:
By reading google's documentation about that topic I learned that I need to use https://.chromiumapp.org endpoint for webAuthFlow redirect url, which I did and everything worked fine. But now google wants me to prove my ownership of chromiumapp.org, which is unclear to me...
Here's the process of setting chromiumapp domain url as redirect url:
First I added https://my-extension-id.chromiumapp.org to Authorised redirect URIs section in google developers console.
Then, google notified me that chromiumapp.org domain needs to be added to Authorised domains section first (under consent screen tab) in order to be able to add it toAuthorised redirect URIs section. So, I added chromiumapp.org to Authorised domains
And now, when I apply for verification process, google wants me to verify my ownership of chromiumapp.org
Although I don't think that webAuthFlow code is relevant here, but here it is, just in case:
chrome.identity.launchWebAuthFlow(
{
"url": "https://accounts.google.com/o/oauth2/auth?" +
$.param({
"client_id": settings.CLIENT_ID,
"scope": settings.SCOPE,
"redirect_uri": getRedirectUri(),
"response_type": "code",
"access_type": "offline",
"login_hint": "",
"prompt": "consent select_account"
}),
"interactive": true
},
callback
);
My question is:
What am I doing wrong here?
Thanks!

simple form symfony2 firewall redirection

Here is my issue.
Situation:
I am trying to add some custom logic during user login. I could find to ways to do so:
hard way (but with a lot of control); building my own authentication provider, following this guidelines of the cookbook or this complementing publication of vandenbrand
easy way (exactly what I need ): use simple_form. simple_form is a key which has the same options as form_login, but for which I can define an "authenticator".
cookbook tuto I used can be found here
Issue
I had an existing and operational app/security.yml configuration with 'form_login' key.
secured_area:
pattern: ^/foo/user/secured/
form_login:
check_path: /foo/user/secured/login_check
login_path: /foo/user/login
I followed steps of the tutorial described above. therefore, my security.yml gets modified to:
secured_area:
pattern: ^/foo/user/secured/
#form_login:
simple_form:
authenticator: foo_authenticator
check_path: /foo/user/secured/login_check
login_path: /foo/user/login
when I try to access a page /foo/user/secured/target of the secured area, the firewall does its job: it catches the query and asks for credentials (via intermediary page /foo/user/login).
However, once right credentials input (and obviously validated), I keep staying on the same page. It does not redirect to the page /foo/user/secured/target I was asking for in the first place. There is no refreshing to trying to go to that page via new request: I remain stuck at login stage.
EDIT 1: here are the steps I identify based on logs and debugging:
1) user tries to access /foo/user/secured/target, for which you need to be identified at least with ROLE_USER to access
2) firewall intercepts this request, as it matches listened routes (app/config/security.yml):
secured_area:
pattern: ^/foo/user/secured/
3) it redirects toward login route
4) user fills in with username and password, and submits post
5) when form is received, a token gets created by createToken method of custom authenticater. It returns an object of class UsernamePasswordToken created with parameter username, password in clear, authenticater key: UsernamePasswordToken($username, $password, $providerKey)
6) token gets passed onto authenticateToken method de of authenticater object. this method compares clear password hash contained in token andd accessed through $token->getCredentials()) with hashed password in database.
7) authentication worked: we get redirected toward /foo/user/secured/target . token and user get serialized in session (ISSUE STARTS HERE: indeed, user clear password is erased so that it doesn't leave tracks in session, and getCredentials() will return empty string now).
8) while loading page, le firewall is activated. It detects user logged in, seems to want to check its token. Therefore, it calls authenticateToken.
9) authenticateToken tries to compare sha1($token->getCredentials()) to hashed password in database. comme $token->getCredentials() is empty, comparison fails. authenticateToken raises an exception.
10) raised exception triggers firewall redirection toward login page. There we are: stuck in infinite loop landing systematically on login page.
STOP EDIT 1.
Solution
Does anyone know why this change of behaviour between 'form_login' and 'simple_form'? Most of all, would you know a good way to fix this ? I guess authenticate method or custom authenticater should be slightly changed, but I am not yet confident enough with security to solve this elegantly.
Many thanks in advance.
Kind regards,
Wisebes
You have to use some string (not the object) from sample. Or implement __toString() for User entity.
NOT
return new UsernamePasswordToken($user, ...
USE
return new UsernamePasswordToken($user->getEmail() or whatever, ...
if you want to access to the page you was requesting, you could use any of the options that Symfony offers to you:
Redirecting after Login:
always_use_default_target_path (type: Boolean, default: false)
default_target_path (type: string, default: /)
target_path_parameter (type: string, default: _target_path)
use_referer (type: Boolean, default: false)
You could see the section of the book 'SecurityBundle Configuration ("security")'
http://symfony.com/doc/current/reference/configuration/security.html
I hope that this be useful for you.
Kind regards.
well, as I was not able to make it work fine, I created my own custom authentication provider. I hope the issue reported above will be fixed asap. If anyone has got an answer, I still am interested!
For other people facing the same issue, I recommend creating a custom authentication provider. You may even inherit from existing authentication provider, and therefore limit modifications to be done. All in all, you are able to add your custom logic with a limited amount of trouble that way.

Pulling user's name and photo with Passport.js

I am developing a node.js app and recently figured out how to authenticate via GitHub. I want to know if there is a way to pull a user's profile photo and name so I can display it elsewhere in the app. I found this question, but it looks like Facebook and Google use different methods of obtaining these things.
Can someone point me in the right direction?
Passport module developers usually normalize the user profile object so some standard fields are available in the same way across all modules in this way:
profile.id - assigned by the provider
profile.username - their 'login'
profile.displayName - full name of the user
profile.profileUrl - user's profile page on the provider's site
profile.emails - array of email addresses, but usually just a single address
Thus, you already have the username and/or displayname. One down!
These cover what is consistently needed, but providers can return other information. This naturally depends upon (a) what kind of services the provider offers and (b) the requested scopes.
The provider-specific info isn't lost. It is stored in profile._json next to the normalized properties...and inspecting this will show what else you have to work with.
For Github profile photos/images, you'll be looking for a gravatar_id property to get the user's photo URL.
You can confirm this, using the boilerplate example from passport-github for illustration purposes only, you could do something like this to see what Github is handing back to you so you can evaluate the entire provider response:
passport.use(new GitHubStrategy({
// authentication stuff here, per `passport-github` docs
},
function(accessToken, refreshToken, profile, done) {
// skipping error handling &c for brevity...
fs.writeFile("githubProfile.json", JSON.stringify(profile));
return done(null, profile);
});
}
));
If correct, you could then grab the user photo URL from profile._json.gravatar for use in whatever way you need (saving to database, inserting into a profile page, etc).

Resources