Passport Facebook strategy returns undefined values - passport-facebook

I am using the passport-facebook plugin in a NextJS app and my test script defines the strategy as below:
// Configure Passport
// ---------------------------------------------------------------
passport.use(new LocalStrategy(User.authenticate()));
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: process.env.FACEBOOK_APP_CALLBACK,
},
function (accessToken, refreshToken, profile, done) {
console.log(profile);
}
));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// ---------------------------------------------------------------
My authentication routes are:
// Facebook
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/success',
failureRedirect: '/failure',
}),
);
All I'm trying to do with this for now, is to display all the values returned by Facebook upon a successful authentication. The authentication works as expected but Facebook seems to be returning undefined for most keys in the profile object:
{ id: '1234567812345677',
username: undefined,
displayName: 'John Doe',
name:
{ familyName: undefined,
givenName: undefined,
middleName: undefined },
gender: undefined,
profileUrl: undefined,
provider: 'facebook',
_raw: '{"name":"John Doe","id":"1234567812345677"}',
_json: { name: 'John Doe', id: '1234567812345677' } }
All I get is the displayName and id; everything else is undefined. What's going wrong? A very similar question was asked here before but none of the answers (no accepted answer) offered address the problem.

I have no experience in this area, but from looking at the readme of facebook-passport, it sounds like you need to use the profileFields in your FacebookStrategy. :
The Facebook profile contains a lot of information about a user. By
default, not all the fields in a profile are returned. The fields
needed by an application can be indicated by setting the profileFields
option.
new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback",
profileFields: ['id', 'displayName', 'photos', 'email']
}), ...)
Refer to the User section of the Graph API Reference for the complete
set of available fields.

Related

Nuxt.js exchanging authorization code for access token Oauth2

I'm trying to exchange the authorization code I got in the first step of the documentation for access token. Where I'm stuck is how to send a request for the token that contains the code I've just got with the first request.
This is my code:
auth: {
redirect: {
login: '/',
callback: '/auth'
},
strategies: {
wrike: {
scheme: 'oauth2',
endpoints: {
authorization: 'https://login.wrike.com/oauth2/authorize/v4',
token: 'https://login.wrike.com/oauth2/token',
logout: '/'
},
token: {
property: 'access_token',
type: 'Bearer',
maxAge: 1800
},
responseType: 'code',
grantType: 'authorization_code',
accessType: 'offline',
clientId: XXXX,
client_secret: YYYY
}
}
}
I can't figure it out how I should set up the redirect URI, in the client or in the server side? How should I do the second request? (This below)
POST https://login.wrike.com/oauth2/token
//Parameters:
client_id=<client_id>
client_secret=<client_secret>
grant_type=authorization_code
code=<authorization_code>
I think Edward is right. It doesn't seem to work. You can either do the custom schema which is what I am going to do, or you can do what I currently have which is something like this (of course ignore all the console.log and stuff like that):
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const state = urlParams.get('state')
console.log('state', state)
console.log('stateStorage', window.localStorage.getItem(state))
if ((code && state) && state === window.localStorage.getItem('state')) {
this.$axios.post('http://publisher-local.co.uk:8080/oauth/token', {
grant_type: 'authorization_code',
client_id: 5,
redirect_uri: 'http://localhost:3000/auth',
code_verifier: window.localStorage.getItem('verifier'),
code
}).then(response => {
this.$auth.setUserToken(response.data.access_token)
this.$auth.fetchUser()
})
}
So basically after you are redirected back to your client after logging in on the server page just look for the details in the URL and make the request yourself.

Change request payload in Nuxt Auth

I have this Facebook strategy:
facebook: {
access_token_endpoint: 'http://***.**/api/v0/auth/social',
access_type: 'offline',
client_id: '*******',
grant_type: 'authorization_code',
redirect_uri: socialLoginUrl + '/account/aanmelden',
response_type: 'code',
token_key: 'jwt',
userinfo_endpoint: 'https://****.***.**/user/profile'
},
When I try to register with Facebook I get the following form in the request:
code: **
client_id: **
redirect_uri: **
response_type: **
grant_type: **
I want to supply some data to the back-end when I register:
"attributes":{
"code":"*****",
"vendor":"Facebook"
},
How do I add this to the form that's being sent to the access_token_endpoint ?
// updated question.
Calling the loginWith function:
#click="$auth.loginWith('facebook', { params: data })"
data object:
data () {
return {
data: {
type: 'user',
attributes: {
vendor: 'Facebook',
code: '**'
}
},
}
},
Request payload in the browser:
code=**&client_id=**&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Faccount%2Faanmelden&response_type=code&grant_type=authorization_code
Response from the back-end:
I expect the data object to be available in the payload, but I'm not sure if I'm doing this correctly.
From the official docs, it looks like you can do
this.$auth.loginWith('facebook', { params: { /* additional authentication parameters */ } })
.then(() => this.$toast.success('Logged In!'))
I never used it with Facebook but it's working great with local (using JWT).
The related part of the documentation: https://auth.nuxtjs.org/api/auth#loginwithstrategyname-args

Create external_account for Stripe Connect payouts with Stripe.js (iOS)

I am trying to connect actual bank accounts to the stripe accounts in Stripe Connect.
However, I am struggling with the actual implementation.
I use Custom Accounts, so I want to provide the user with the account creation logic through my iOS app.
In the Stripe API Reference it says that the recommended way to accomplish this is:
"Destination accounts are added via the external_accounts parameter when creating or updating Custom accounts. The value should be a bank account or debit card token returned from Stripe.js."
Creating the token is documented as follows (I am using NodeJS):
stripe.createToken('bank_account', {
country: 'US',
currency: 'usd',
routing_number: '110000000',
account_number: '000123456789',
account_holder_name: 'Jenny Rosen',
account_holder_type: 'individual',
}).then(function(result) {
// Handle result.error or result.token
});
Where to I link that token in the account creation process? See related code below:
app.post('/create_account', (req, res) => {
console.log('create account called');
var email = req.body.email;
var firstname = req.body.firstname;
var lastname = req.body.lastname;
stripe.accounts.create({
country: "CH",
type: "custom",
email: email,
business_name: "examplename",
legal_entity: {
first_name: "firstname",
last_name: "lastname",
dob: {
day: 1,
month: 1,
year: 1900
}
}
}).then((account) => {
res.status(200).send(account)
}).catch((err) => {
console.log(err, req.body)
res.status(500).end()
});
});
Is the token creation just a means of validating the account information client-side?
Would be glad if someone can elaborate on this with a simple step-by-step explanation, thank you in advance!
You'd pass the token in the external_account parameter:
var bankAccountToken = req.body.stripeToken;
stripe.accounts.create({
country: "CH",
type: "custom",
// ...
external_account: bankAccountToken,
}).then((account) => {
// ...

Hapi Bell Twitter Auth with email

I'm struggling to get the email address of twitter users when they login
I get the following error from Joi "Error: Uncaught error: Invalid options value: must be true, falsy or an object"
server.auth.strategy('twitter', 'bell', {
provider: 'twitter',
scope: ['public_profile', 'email'],
config: {
extendedProfile: true,
getParams: 'include_email',
getMethod: 'account/verify'
},
password: config.longpass, //Use something more secure in production
clientId: config.twitter_key,
clientSecret: config.twitter_secret,
isSecure: config.useHttps //Should be set to true (which is the default) in production
});
This code works for me.
server.auth.strategy('twitter', 'bell', {
provider: 'twitter',
config: {
getMethod: 'account/verify_credentials',
getParams: {include_email:'true' },//doesn't work without quotes!
},
password: 'secret_cookie_encryption_password', //Use something more secure in production
clientId: secret.twitterId,
clientSecret: secret.twitterSecret,
isSecure: false //Should be set to true (which is the default) in production
});
Don't forget to allow necessary permission (Request email addresses from users) in your Twitter application settings.

OAuth 2.0 Scope for Google Apps users' names with google-api-nodejs-client

I'm trying to use Google's 'google-api-nodejs-client' package (https://github.com/google/google-api-nodejs-client) to handle OAuth 2.0 authentication.
I've modified the example in examples/oauth2.js to console.log the entire profile object.
What scope can I use to correctly extract users' 'givenName' and 'familyName' if they're authenticating using a Google Apps account? Using the following scope:
scope: [
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read'
]
returns the following response once authenticated:
{ kind: 'plus#person',
etag: '"LONG STRING"',
emails: [ { value: 'example#example.example', type: 'account' } ],
objectType: 'person',
id: '123456',
displayName: '',
name: { familyName: '', givenName: '' },
image:
{ url: 'https://lh3.googleusercontent.com/ etc etc',
isDefault: false },
isPlusUser: false,
language: 'en_GB',
circledByCount: 0,
verified: false,
domain: 'example.example' }
I tried fooling around with the API on the API Explorer (https://developers.google.com/apis-explorer/#p/plus/v1/plus.people.get?userId=me) and only needed the 'https://www.googleapis.com/auth/plus.login' scope to get my familyName and givenName.
Perhaps the user that you are requesting the data from does not have a given and family name set?

Resources