Authentication using linkedin in a mean stack application - node.js

so I've been trying to implement login with linkedin in my application, and I couldn't find anything online that could show me the steps from A to Z
I implemented the backend and the frontend separateley, however, I don't know how to link them together
In the backend, I'm using passportjs
So here's what I've done so far:
FRONTEND
app.component.html
<button click="loginWithLinkedin()">Linkedin</button>
app.component.ts
window.location.href = `https://www.linkedin.com/uas/oauth2/authorization?response_type=code&state=true&client_id=${environment.LINKEDIN_API_KEY}&redirect_uri=${environment.LINKEDIN_REDIRECT_URL}&scope=${environment.LINKEDIN_SCOPE}`;
redirect.component.ts
const linkedInToken = this.route.snapshot.queryParams["code"];
this.http.get('http://localhost:3000/user/auth/linkedin',
{ params: { token: linkedinToken }}).subscribe(res => {
console.log(res);
});
BACKEND
passport.use(new LinkedInStrategy({
clientID: LINKEDIN_CLIENT_ID,
clientSecret: LINKEDIN_CLIENT_SECRET,
callbackURL: "http://127.0.0.1:8000/user/auth/linkedin/callback",
scope: ['r_emailaddress', 'r_basicprofile'],
passReqToCallback: true
},
function (req, accessToken, refreshToken, profile, done) {
req.session.accessToken = accessToken;
process.nextTick(function () {
return done(null, profile);
});
}));
linkedinRouter.route('/auth/linkedin')
.get(passport.authenticate('linkedin', { state: 'SOME STATE' }),
function(req, res){
// The request will be redirected to LinkedIn for authentication, so this
// function will not be called.
});
linkedinRouter.route('/auth/linkedin/callback')
.get( passport.authenticate('linkedin', { failureRedirect: '/' }),
function (req, res) {
return res.send('hello');
});
I don't understand how would passport work and I don't understand how to link backend and frontend.
I don't know if this is the correct way to implement linkedin authentication
If you have any articles that could guide, or if you can correct that would really help, I've been stuck for a couple of days now.
Thank you very much

I apologize if I formulated the question in a bad way or I didn't know how to ask the question. However, I managed to make it work and I wrote a medium article about it.
here's the link:
https://nour-karoui.medium.com/linkedin-authentication-for-a-mean-stack-application-bd8542b2dc7f
I hope it can help somebody out there !

Related

Next.js implementing google signin with /api routes and passport

I'm trying to implement Google signin in my serverless (/api routes) next.js app.
I'm using #passport-next/passport-google-oauth2, next-connect and passport packages.
I searched a lot and found a few helpful links online but I couldn't make it work, and I'm not sure about the whole flow that should happen here.
For example, I found those:
https://github.com/andycmaj/nextjs-passport-session-auth
https://todayilearned.io/til/nextjs-with-passport-oauth-cookie-sessions
I have /api/auth/login route for regular login. If login was successful, I'm setting JWT cookie on user response.
For Google login, I added /api/auth/social/google route, with the following code:
import passport from 'passport';
import { Strategy as GoogleStrategy } from '#passport-next/passport-google-oauth2';
import nextConnect from 'next-connect';
passport.use(new GoogleStrategy({
clientID: process.env.OAUTH_GOOGLE_CLIENT_ID,
clientSecret: process.env.OAUTH_GOOGLE_CLIENT_SECRET,
callbackURL: process.env.OAUTH_GOOGLE_CALLBACK_URL,
scope: "https://www.googleapis.com/auth/plus.login",
},
(accessToken, refreshToken, googleUserInfo, cb) => {
console.log('accessToken, refreshToken, googleUserInfo');
cb(null, googleUserInfo);
}
));
export default nextConnect()
.use(passport.initialize())
.get(async (req, res) => {
passport.authenticate('google')(req, res, (...args) => {
console.log('passport authenticated', args)
})
})
and /api/auth/social/callback/google route, with the following code:
import passport from 'passport';
import nextConnect from 'next-connect';
passport.serializeUser((user, done) => {
console.log('serialize')
done(null, user);
});
export default nextConnect()
.use(passport.initialize())
.get(async (req, res) => {
passport.authenticate('google', {
failureRedirect: '/failure/success',
successRedirect: '/auth/success',
})(req, res, (...args) => {
console.log('auth callback')
return true;
})
})
So what happens is that the user is redirected to /auth/success after signin to his google account, and console logs are:
accessToken, refreshToken, googleUserInfo
serialize
So my questions are:
When and how can I set the JWT cookie on the response to "login" the user?
Why the line console.log('auth callback') never runs? when it should run?
The same for console.log('passport authenticated', args)
How is a complete flow should look like in my app?
Thanks !
I had the same problem. I'm still working on the full implementation, but according to this thread it looks like the problem might be that passport.authenticate is supposed to be used as a middleware:
// api/auth/social/callback/google
export default nextConnect()
.use(passport.initialize())
.get(passport.authenticate("google"), (req, res) => {
console.log('auth callback')
res.writeHead(302, {
'Location': '/auth/success'
});
res.end();
})
Ok, I'm not a Next.js expert but I had a similar "problem", only using other authentication method.
You see, the framework has a method that is really important in the authentication process, they are called: getInitialProps, which is an async function that can be added to any page as a static method to trigger before the initial render;
it looks like this:
static async getInitialProps(ctx) {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const json = await res.json()
return { stars: json.stargazers_count }
}
It takes this ctx prop, which is a object with {req, res} that you can use to make your request to authenticate the user and, then, you may use req with the lib next-cookies to get the JWT token and check if it is valid and, then, you may return an object, which will be used as a prop of your page (or all the pages, if you wrap your _app.js around a Context of Authentication.
Also, your 'auth callback' is not being called because you redirect the user before it triggers, which is not happening. The same for 'passport authenticated'
This article may also help you.
https://dev.to/chrsgrrtt/easy-user-authentication-with-next-js-18oe

Passport Github strategy not working and throwing errors

The code below is getting mad at me. I don't see anything wrong with it.
function User(profile){
console.log(profile)
}
passport.use(
new GitHubStrategy({
clientID: "my_id",
clientSecret: "secret",
callbackURL: "http://localhost:3000/auth/github/callback",
},
function(accessToken, refreshToken, profile, done) {
User(profile),function (err, user) {
return done(err, user);
};
}
)
);
app.get(
"/auth/github",
passport.authenticate("github", { scope: ["user:email"] })
);
app.get(
"/auth/github/callback",
passport.authenticate("github", { failureRedirect: "/login" }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect("/");
}
);
It's throwing a big error every time I try to authenticate. Please help.
Edited the question and did as #jasonandmonte said and now I get this:
The issue I am seeing is you are defining a User function that is only logging the profile. The User function in the documentation is an example of a database model that queries a database and passes data to a callback.
To resolve the issue and replicate how passport-github's example does it, you will need to use an object modeling tool like Mongoose or Sequelize. You will then have access to something similar to User.findOrCreate() or just User.find() if you want to restrict account creation to an admin role.
To get passport working until you setup a database connection though, you should be able to update the strategy callback to invoke done.
passport.use(
new GitHubStrategy({
clientID: "my_id",
clientSecret: "secret",
callbackURL: "http://localhost:3000/auth/github/callback",
},
function(accessToken, refreshToken, profile, done) {
done(null, profile.id);
}
)
);

access_token not present in the passport-github2 request

I have registered an OAuth App via my Github account. I am basically trying to authorize my node requests(by sending access_token as part of request cookies) so I can access few APIs on another server. Hence I am using the github-passport2 package. I have setup the github strategy etc. & it seems to be all according to the doc. The flow works well too.
My Issue
After logging into Github(authorized) & getting redirected back to my /auth/github/callback, I ideally should be authorized and should have an access_token in the req. But I don't have it! Because of this I am not able to authorize my future requests with an access_token.
Important to note is that, this access_token is automatically attached when the request is initiated from a browser/client(using withCredentials: true parameter). The same access_token via node doesn't seem to be retrievable.
passport.use(new GitHubStrategy({
clientID: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET,
callbackURL: "http://localhost:8080/auth/github/callback",
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile);
});
}
));
app.get('/auth/github', passport.authenticate('github', { scope: [ 'user:email' ] }), function(req, res){
// The request will be redirected to GitHub for authentication, so this
// function will not be called.
});
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), function(req, res) {
console.log(req); // <- This ideally should have the access_token? but doesn't
});
I have struggling for days on this. Any help is much appreciated.

Node React Google Login

I have been learning react and node together and have been trying to implement using google auth. I believe I have the front end side working as I can get an access token back but I can't seem to complete the authentication with the node side of it. Here is my React code.
export default class GoogleLoginComponent extends Component {
responseGoogle(response){
var id_token = response.getAuthResponse().id_token;
var googlePlus = '101603157010265563225'
console.log({accessToken: id_token});
//axios.get('oauth',id_token)
}
render(){
return(
<GoogleLogin
clientId="115435392551-qamvp0loln91e4d2uoat8pnki4f705o6.apps.googleusercontent.com"
buttonText="Login"
onSuccess={this.responseGoogle.bind(this)}
onFailure={this.responseGoogle.bind(this)}
/>
)
}
}
This will print out the id_token successfully for me. My issue I believe at least(but what do I know) is on the server side. In google I set up oauth as the callback address. Will Google make the get call to oauth or do I have to do it? When I try and do it myself I get a whole mess of errors. Here is the server side code.
var GoogleStrategy = require( 'passport-google-oauth2' ).Strategy;
passport.use(new GoogleStrategy({
clientID: "115435392551-qamvp0loln91e4d2uoat8pnki4f705o6.apps.googleusercontent.com",
clientSecret: "_9tCI3_e-oKFwz1kFkxvRKMM",
callbackURL: "http://localhost:3000/oauth",
passReqToCallback : true
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return done(err, user);
});
}
));
app.get( '/oauth',
passport.authenticate( 'google', {
successRedirect: 'success.html',
failureRedirect: 'fail.html'
})
);
Any ideas would be greatly appreciated.

Using PassportJS google authentication with the nodejs google api library

I'm currently looking at implementing a google api, using the nodejs client:
https://github.com/google/google-api-nodejs-client/
I'm trying to use passport in order to authenticate, which seems to be working#
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function () {
var user = {
id: profile.id,
email: profile.email,
firstName: profile.given_name,
lastName: profile.family_name,
accessToken: accessToken
};
return done(null, user);
});
}
));
In my google auth callback:
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
//do something here with the google api
});
I can get hold of req.user, and this has the accessToken
However, the docs for the Google api nodejs client aren't clear on how to use an accessToken.
The example included shows the OAauth2Client retrieving a token, but I guess that part has already been covered using Passport?
I'm not familiar with google-api-nodejs-client, but this is in their documentation:
oauth2Client.credentials = {
access_token: 'ACCESS TOKEN HERE',
refresh_token: 'REFRESH TOKEN HERE'
};
client
.plus.people.get({ userId: 'me' })
.withAuthClient(oauth2Client)
.execute(callback);
I assume you can just set the credentials to those provided by Passport, and things will work fine.
Honestly, though, I find these API wrappers really contrived, and recommend just using request. That way you can access any API service from any provider using a familiar module.

Resources