Fixed several typos in advanced-express-tools.json

pull/13342/head
RamiroPinol 2017-02-14 14:54:14 -03:00
parent f5129f0ba6
commit eadb4a2354
1 changed files with 32 additions and 32 deletions

View File

@ -28,7 +28,7 @@
"title": "Setting up a Template Engine",
"description": [
"A template engine enables you to use static template files (such as those written in <em>Pug</em>) in your app. At runtime, the template engine replaces variables in a template file with actual values which can be supplied by your server, and transforms the template into a static HTML file that is then sent to the client. This approach makes it easier to design an HTML page and allows for displaying of variables on the page without needing to make an API call from the client.",
"To set up <em>Pug</em> for use in your project, you will need to add it as a dependancy first in your package.json. <code>\"pug\": \"^0.1.0\"</code>",
"To set up <em>Pug</em> for use in your project, you will need to add it as a dependency first in your package.json. <code>\"pug\": \"^0.1.0\"</code>",
"Now to tell Node/Express to use the templating engine you will have to tell your express <b>app</b> to <b>set</b> 'pug' as the 'view-engine'. <code>app.set('view engine', 'pug')</code>",
"Lastly, we should change our response to the request for the index route to <code>res.render</code> with the path to the view <em>views/pug/index.pug</em>.",
"If all went as planned, you should refresh your apps home page and see a small message saying you're successfully rending the Pug from our Pug file! Submit your page when you think you've got it right."
@ -60,7 +60,7 @@
"description": [
"One of the greatest features of using a template engine is being able to pass variables from the server to the template file before rendering it to HTML.",
"In your Pug file, you're about to use a variable by referencing the variable name as <code>#{variable_name}</code> inline with other text on an element or by using an equal side on the element without a space such as <code>p= variable_name</code> which sets that p elements text to equal the variable.",
"We strongly recomend looking at the syntax and structure of Pug <a href='https://github.com/pugjs/pug'>here</a> on their Githubs README. Pug is all about using whitespace and tabs to show nested elements and cutting down on the amount of code needed to make a beautiful site.",
"We strongly recommend looking at the syntax and structure of Pug <a href='https://github.com/pugjs/pug'>here</a> on their Githubs README. Pug is all about using whitespace and tabs to show nested elements and cutting down on the amount of code needed to make a beautiful site.",
"Looking at our pug file 'index.pug' included in your project, we used the variables <em>title</em> and <em>message</em>",
"To pass those alone from our server, you will need to add an object as a second argument to your <em>res.render</em> with the variables and their value. For example, pass this object along setting the variables for your index view: <code>{title: 'Hello', message: 'Please login'</code>",
"It should look like: <code>res.render(process.cwd() + '/views/pug/index', {title: 'Hello', message: 'Please login'});</code>",
@ -84,9 +84,9 @@
"title": "Setting up Passport",
"description": [
"It's time to set up <em>Passport</em> so we can finally start allowing a user to register or login to an account! In addition to Passport, we will use Express-session to handle sessions. Using this middleware saves the session id as a cookie in the client and allows us to access the session data using that id on the server. This way we keep personal account information out of the cookie used by the client to verify to our server they are authenticated and just keep the <em>key</em> to access the data stored on the server.",
"To set up Passport for use in your project, you will need to add it as a dependancy first in your package.json. <code>\"passport\": \"^0.3.2\"</code>",
"In addition, add Express-session as a dependancy now as well. Express-session has a ton of advanced features you can use but for now we're just going to use the basics! <code>\"express-session\": \"^1.15.0\"</code>",
"You will need to set up the session settings now and initilize Passport. Be sure to first create the variables 'session' and 'passport' to require 'express-session' and 'passport' respectively.",
"To set up Passport for use in your project, you will need to add it as a dependency first in your package.json. <code>\"passport\": \"^0.3.2\"</code>",
"In addition, add Express-session as a dependency now as well. Express-session has a ton of advanced features you can use but for now we're just going to use the basics! <code>\"express-session\": \"^1.15.0\"</code>",
"You will need to set up the session settings now and initialize Passport. Be sure to first create the variables 'session' and 'passport' to require 'express-session' and 'passport' respectively.",
"To set up your express app to use use the session we'll define just a few basic options. Be sure to add 'SESSION_SECRET' to your .env file and give it a random value. This is used to compute the hash used to encrypt your cookie!",
"<pre>app.use(session({\n secret: process.env.SESSION_SECRET,\n resave: true,\n saveUninitialized: true,\n}));</pre>",
"As well you can go ahead and tell your express app to <b>use</b> 'passport.initialize()' and 'passport.session()'. (For example, <code>app.use(passport.initialize());</code>)",
@ -121,7 +121,7 @@
"id": "5895f70cf9fc0f352b528e66",
"title": "Serialization of a User Object",
"description": [
"Serialization and deserialization are important concept in reguards to authentication. To serialize an object means to convert its contents into a small <em>key</em> essentially that can then be deserialized into the original object. This is what allows us to know whos communicated with the server without having to send the authentication data like username and password at each request for a new page.",
"Serialization and deserialization are important concepts in regards to authentication. To serialize an object means to convert its contents into a small <em>key</em> essentially that can then be deserialized into the original object. This is what allows us to know whos communicated with the server without having to send the authentication data like username and password at each request for a new page.",
"To set this up properly, we need to have a serialize function and a deserialize function. In passport we create these with <code>passport.serializeUser( OURFUNCTION )</code> and <code>passport.dederializeUser( OURFUNCTION )</code>",
"The serializeUser is called with 2 arguments, the full user object and a callback used by passport. Returned in the callback should be a unique key to identify that user- the easiest one to use being the users _id in the object as it should be unique as it generated by MongoDb. Similarly deserializeUser is called with that key and a callback function for passport as well, but this time we have to take that key and return the users full object to the callback. To make a query search for a Mongo _id you will have to create <code>const ObjectID = require('mongodb').ObjectID;</code>, and then to use it you call <code>new ObjectID(THE_ID)</code>. Be sure to add MongoDB as a dependency. You can see this in the examples below:",
"<pre>passport.serializeUser((user, done) => {\n done(null, user._id);\n });</pre><br><pre>passport.deserializeUser((id, done) => {\n db.collection('users').findOne(\n {_id: new ObjectID(id)},\n (err, doc) => {\n done(null, doc);\n }\n );\n });</pre>",
@ -135,7 +135,7 @@
"testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.serializeUser/gi, 'You should have created your passport.serializeUser function'); assert.match(data, /null, user._id/gi, 'There should be a callback in your serializeUser with (null, user._id)'); }, xhr => { throw new Error(xhr.statusText); })"
},
{
"text": "Deserialize user function corrent",
"text": "Deserialize user function correct",
"testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.deserializeUser/gi, 'You should have created your passport.deserializeUser function'); assert.match(data, /null,( |)null/gi, 'There should be a callback in your deserializeUser with (null, null) for now'); }, xhr => { throw new Error(xhr.statusText); })"
},
{
@ -157,8 +157,8 @@
"id": "5895f70cf9fc0f352b528e67",
"title": "Implement the Serialization of a Passport User",
"description": [
"Right now we're not loading an actually users object since we havn't set up our database. This can be done many different ways, but for our project we will connect to the database once when we start the server and keep a persistant connection for the full life-cycle of the app.",
"To do this, add MongoDB as a depenacy and require it in your server. (<code>const mongo = require('mongodb').MongoClient;</code>)",
"Right now we're not loading an actually users object since we haven't set up our database. This can be done many different ways, but for our project we will connect to the database once when we start the server and keep a persistent connection for the full life-cycle of the app.",
"To do this, add MongoDB as a dependency and require it in your server. (<code>const mongo = require('mongodb').MongoClient;</code>)",
"Now we want to the connect to our database then start listening for requests. The purpose of this is to not allow requests before our database is connected or if there is a database error. To accomplish you will want to encompass your serialization and your app listener in the following:",
"<pre>mongo.connect(process.env.DATABASE, (err, db) => {\n if(err) {\n console.log('Database error: ' + err);\n } else {\n console.log('Successful database connection');\n\n //serialization and app.listen\n\n}});</pre>",
"You can now uncomment the block in deserializeUser and remove your <code>done(null, null)</code>. Be sure to set <em>DATABASE</em> in your .env file to your database's connection string (for example: <code>DATABASE=mongodb://admin:pass@mlab.com:12345/my-project</code>). You can set up a free database on <a href='https://mlab.com/welcome/'>mLab</a>. Congratulations- you've finished setting up serialization!",
@ -185,9 +185,9 @@
"id": "5895f70df9fc0f352b528e68",
"title": "Authentication Strategies",
"description": [
"A strategy is a a way of authenticating a user. You can use a strategy for allowing users to authenticate based on localally saved infomation(if you have them register first) or from a variety of providers such as Google or Github. For this project we will set up a local strategy. To see a list of the 100's of strategies, visit Passports site <a href='http://passportjs.org/'>here</a>.",
"Add <em>passport-local</em> as a dependancy and add it to your server as follows: <code>const LocalStrategy = require('passport-local');</code>",
"Now you will have to tell passport to <b>use</b> an instantiated LocalStartegy object with a few settings defined. Make sure this as well as everything from this point on is encapuled in the database connection since it relys on it! <pre>passport.use(new LocalStrategy(\n function(username, password, done) {\n db.collection('users').findOne({ username: username }, function (err, user) {\n console.log('User '+ username +' attempted to log in.');\n if (err) { return done(err); }\n if (!user) { return done(null, false); }\n if (password !== user.password) { return done(null, false); }\n return done(null, user);\n });\n }\n));</pre> This is defining the process to take when we try to authenticate someone locally. First it trys to find a user in our database with the username entered, then it checks for the password to match, then finally if no errors have popped up that we checked for, like an incorrect password, the users object is returned and they are authenticated.",
"A strategy is a way of authenticating a user. You can use a strategy for allowing users to authenticate based on locally saved information (if you have them register first) or from a variety of providers such as Google or Github. For this project we will set up a local strategy. To see a list of the 100's of strategies, visit Passports site <a href='http://passportjs.org/'>here</a>.",
"Add <em>passport-local</em> as a dependency and add it to your server as follows: <code>const LocalStrategy = require('passport-local');</code>",
"Now you will have to tell passport to <b>use</b> an instantiated LocalStartegy object with a few settings defined. Make sure this as well as everything from this point on is encapsulated in the database connection since it relies on it! <pre>passport.use(new LocalStrategy(\n function(username, password, done) {\n db.collection('users').findOne({ username: username }, function (err, user) {\n console.log('User '+ username +' attempted to log in.');\n if (err) { return done(err); }\n if (!user) { return done(null, false); }\n if (password !== user.password) { return done(null, false); }\n return done(null, user);\n });\n }\n));</pre> This is defining the process to take when we try to authenticate someone locally. First it tries to find a user in our database with the username entered, then it checks for the password to match, then finally if no errors have popped up that we checked for, like an incorrect password, the users object is returned and they are authenticated.",
"Many strategies are set up using different settings, general it is easy to set it up based on the README in that strategies repository though. A good example of this is the Github strategy where we don't need to worry about a username or password because the user will be sent to Github's auth page to authenticate and as long as they are logged in and agree then Github returns their profile for us to use.",
"In the next step we will set up how to actually call the authentication strategy to validate a user based on form data! Submit your page when you think you've got it right up to this point."
],
@ -212,9 +212,9 @@
"id": "5895f70df9fc0f352b528e69",
"title": "Using Passport Strategies",
"description": [
"In the index.pug file supplied theres actually a login form. It has previously been hidden because of the inline javascript <code>if showLogin</code> with the form indented after it. Before showLogin as a variable was never defined, it never rendered the code block containing the form. Go ahead and on the res.render for that page add a new variable to the object <code>showLogin: true</code>. When you refresh your page, you should then see the form! This form is set up to <b>POST</b> on <em>/login</em> so this is where we should set up to accept the POST and authenticate the user.",
"In the index.pug file supplied there is actually a login form. It has previously been hidden because of the inline javascript <code>if showLogin</code> with the form indented after it. Before showLogin as a variable was never defined, it never rendered the code block containing the form. Go ahead and on the res.render for that page add a new variable to the object <code>showLogin: true</code>. When you refresh your page, you should then see the form! This form is set up to <b>POST</b> on <em>/login</em> so this is where we should set up to accept the POST and authenticate the user.",
"For this challenge you should add the route /login to accept a POST request. To authenticate on this route you need to add a middleware to do so before then sending a response. This is done by just passing another argument with the middleware before your <code>function(req,res)</code> with your response! The middleware to use is <code>passport.authenticate('local')</code>.",
"<em>passport.authenticate</em> can also take some options as an argument such as: <code>{ failureRedirect: '/' }</code> which is incredibly useful so be sure to add that in as well. As a response after useing the middleware (which will only be called if the authentication middleware passes) should be to redirect the user to <em>/profile</em> and that route should render the view 'profile.pug'.",
"<em>passport.authenticate</em> can also take some options as an argument such as: <code>{ failureRedirect: '/' }</code> which is incredibly useful so be sure to add that in as well. As a response after using the middleware (which will only be called if the authentication middleware passes) should be to redirect the user to <em>/profile</em> and that route should render the view 'profile.pug'.",
"If the authentication was successful, the user object will be saved in <em>req.user</em>.",
"Now at this point if you enter a username and password in the form, it should redirect to the home page <em>/</em> and in the console of your server should be 'User {USERNAME} attempted to log in.' since we currently cannot login a user who isn't registered.",
"Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point <a href='https://gist.github.com/JosephLivengood/8a335d1a68ed9170da02bb9d8f5b71d5'>here</a>."
@ -222,7 +222,7 @@
"challengeSeed": [],
"tests": [
{
"text": "All steps correctly impl in the server.js",
"text": "All steps correctly implemented in the server.js",
"testString": " getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showLogin:( |)true/gi, 'You should be passing the variable \"showLogin\" as true to your render function for the homepage'); assert.match(data, /failureRedirect:( |)('|\")\\/('|\")/gi, 'Your code should include a failureRedirect to the \"/\" route'); assert.match(data, /login[^]*post[^]*local/gi, 'You should have a route for login which accepts a POST and passport.authenticates local'); }, xhr => { throw new Error(xhr.statusText); })"
},
{
@ -240,8 +240,8 @@
"id": "5895f70df9fc0f352b528e6a",
"title": "Creating New Middleware",
"description": [
"As in, any user can just go to /profile whether they authenticated or not by typeing in the url. We want to prevent this by checking if the user is authenticated first before rendering the profile page. This is the perfect example of when to create a middleware.",
"The challenge here is creating the middleware function <code>ensureAuthenticated(req, res, next)</code>, which will check if a user is authenticated by calling passports isAuthenticated on the <em>request</em> which in turn checks for <em>req.user</em> is to be defined. If it is then <em>next()</em> should be called, otherwise we can just respond to the request with a redirect to our homepage to login. An implimentation of this middle ware is:",
"As in, any user can just go to /profile whether they authenticated or not by typing in the url. We want to prevent this by checking if the user is authenticated first before rendering the profile page. This is the perfect example of when to create a middleware.",
"The challenge here is creating the middleware function <code>ensureAuthenticated(req, res, next)</code>, which will check if a user is authenticated by calling passports isAuthenticated on the <em>request</em> which in turn checks for <em>req.user</em> is to be defined. If it is then <em>next()</em> should be called, otherwise we can just respond to the request with a redirect to our homepage to login. An implementation of this middleware is:",
"<pre>function ensureAuthenticated(req, res, next) {\n if (req.isAuthenticated()) {\n return next();\n }\n res.redirect('/');\n};</pre>",
"Now add <em>ensureAuthenticated</em> as a middleware to the request for the profile page before the argument to the get request containing the function that renders the page.",
"<pre>app.route('/profile')\n .get(ensureAuthenticated, (req,res) => {\n res.render(process.cwd() + '/views/pug/profile');\n });</pre>",
@ -250,7 +250,7 @@
"challengeSeed": [],
"tests": [
{
"text": "Middleware ensureAuthenticated should be impl and on our /profile route",
"text": "Middleware ensureAuthenticated should be implemented and on our /profile route",
"testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /ensureAuthenticated[^]*req.isAuthenticated/gi, 'Your ensureAuthenticated middleware should be defined and utilize the req.isAuthenticated function'); assert.match(data, /profile[^]*get[^]*ensureAuthenticated/gi, 'Your ensureAuthenticated middleware should be attached to the /profile route'); }, xhr => { throw new Error(xhr.statusText); })"
},
{
@ -268,8 +268,8 @@
"id": "5895f70ef9fc0f352b528e6b",
"title": "Putting a Profile Together",
"description": [
"Now that we can ensure the user accessing the <em>/profile</em> is authenticated, we can use the infomation contained in 'req.user' on our page!",
"Go ahead and pass the object containing the variable <em>username</em> equaling 'req.user.username' into the render method of the profile view. Then go to youre 'profile.pug' view and add the line <code>h2.center#welcome Welcome, #{username}!</code> creating the h2 element with the class 'center' and id 'welcome' containing the text 'Welcome, ' and the username!",
"Now that we can ensure the user accessing the <em>/profile</em> is authenticated, we can use the information contained in 'req.user' on our page!",
"Go ahead and pass the object containing the variable <em>username</em> equaling 'req.user.username' into the render method of the profile view. Then go to your 'profile.pug' view and add the line <code>h2.center#welcome Welcome, #{username}!</code> creating the h2 element with the class 'center' and id 'welcome' containing the text 'Welcome, ' and the username!",
"Also in the profile, add a link to <em>/logout</em>. That route will host the logic to unauthenticate a user. <code>a(href='/logout') Logout</code>",
"Submit your page when you think you've got it right."
],
@ -318,7 +318,7 @@
"id": "58966a17f9fc0f352b528e6d",
"title": "Registration of New Users",
"description": [
"Now we need to allow a new user on our site to register an account. On the res.render for the home page add a new variable to the object passed along- <code>showRegistration: true</code>. When you refresh your page, you should then see the registration form that was already ctreated in your index.pug file! This form is set up to <b>POST</b> on <em>/register</em> so this is where we should set up to accept the POST and create the user object in the database.",
"Now we need to allow a new user on our site to register an account. On the res.render for the home page add a new variable to the object passed along- <code>showRegistration: true</code>. When you refresh your page, you should then see the registration form that was already created in your index.pug file! This form is set up to <b>POST</b> on <em>/register</em> so this is where we should set up to accept the POST and create the user object in the database.",
"The logic of the registration route should be as follows: Register the new user > Authenticate the new user > Redirect to /profile",
"The logic of step 1, registering the new user, should be as follows: Query database with a findOne command > if user is returned then it exists and redirect back to home <em>OR</em> if user is undefined and no error occurs then 'insertOne' into the database with the username and password and as long as no errors occur then call <em>next</em> to go to step 2, authenticating the new user, which we've already written the logic for in our POST /login route.",
"<pre>app.route('/register')\n .post((req, res, next) => {\n db.collection('users').findOne({ username: req.body.username }, function (err, user) {\n if(err) {\n next(err);\n } else if (user) {\n res.redirect('/');\n } else {\n db.collection('users').insertOne(\n {username: req.body.username,\n password: req.body.password},\n (err, doc) => {\n if(err) {\n res.redirect('/');\n } else {\n next(null, user);\n }\n }\n )\n }\n })},\n passport.authenticate('local', { failureRedirect: '/' }),\n (req, res, next) => {\n res.redirect('/profile');\n }\n);</pre>",
@ -388,11 +388,11 @@
"Create 2 new files: Routes.js and Auth.js",
"Both should start with the following code: <pre>module.exports = function (app, db) {\n\n\n}</pre>",
"Now in the top of your server file, require these files like such: <code>const routes = require('./routes.js');</code>",
"Right after you establish a successful connect with the database instanciate each of them like such: <code>routes(app, db)</code>",
"Right after you establish a successful connect with the database instantiate each of them like such: <code>routes(app, db)</code>",
"Finally, take all of the routes in your server and paste them into your new files and remove them from your server file. Also take the ensureAuthenticated since we created that middleware function for routing specifically. You will have to now correctly add the dependencies in that are used, such as <code>const passport = require('passport');</code>, at the very top above the export line in your routes.js file.",
"Keep adding them untill no more errors exist, and your server file no longer has any routing!",
"Keep adding them until no more errors exist, and your server file no longer has any routing!",
"Now do the same thing in your auth.js file with all of the things related to authentication such as the serialization and the setting up of the local strategy and erase them from your server file. Be sure to add the dependencies in and call <code>auth(app,db)</code> in the server in the same spot. Be sure to have <code>auth(app, db)</code> before <code>routes(app, db)</code> since our registration route depends on passport being initiated!",
"Congratulations- youre at the end of this section of Advanced Node and Express and have some beautiful code to show for it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of the completed project <a href='https://gomix.com/#!/project/delicious-herring'>here</a>."
"Congratulations- you're at the end of this section of Advanced Node and Express and have some beautiful code to show for it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of the completed project <a href='https://gomix.com/#!/project/delicious-herring'>here</a>."
],
"challengeSeed": [],
"tests": [
@ -414,7 +414,7 @@
[
"",
"",
"OAuth 2.0 is the industry-standard authorization and is used accross the internet for social login such as letting you login to freeCodeCamp with your Github account.<br>Implementing social login with passport using OAuth is extremely easy to do beause of the <a href='http://passportjs.org/'>300+ modules</a> already on npm for adding new strategies to your app. In addition to the ease of installation, it is also easier to use because you do not have to deal with a seperate <em>registration</em> or any user imput.<br>To assist in learning to implement this kind of authentication, we've prepared a sample project below currently missing the strategy- you just need to remix it and go to the next challenge to begin! Be sure to enter your database in the .env file- it can be the same one from last project since we're using a new collection!",
"OAuth 2.0 is the industry-standard authorization and is used across the internet for social login such as letting you login to freeCodeCamp with your Github account.<br>Implementing social login with passport using OAuth is extremely easy to do because of the <a href='http://passportjs.org/'>300+ modules</a> already on npm for adding new strategies to your app. In addition to the ease of installation, it is also easier to use because you do not have to deal with a separate <em>registration</em> or any user input.<br>To assist in learning to implement this kind of authentication, we've prepared a sample project below currently missing the strategy- you just need to remix it and go to the next challenge to begin! Be sure to enter your database in the .env file- it can be the same one from last project since we're using a new collection!",
"https://gomix.com/#!/project/fcc-social"
]
],
@ -431,9 +431,9 @@
"title": "Implementation of Social Authentication",
"description": [
"The basic path this kind of authentication will follow in your app is: <ol><li>User clicks a button or link sending them to our route to authenticate using a specific strategy (EG. Github)</li><li>Your route calls <code>passport.authenticate('github')</code> which redirects them to Github.</li><li>The page the user lands on, on Github, allows them to login if they aren't already then asks them to approve access to their profile from our app.</li><li>The user is then returned to our app at a specific callback url with their profile if they approved.</li><li>They are now authenticated and your app should check if it is a returning profile, or save it in your database if it is not.</li></ol>",
"Strategies with OAuth require you to have atleast a <em>Client ID</em> and a <em>Client Secret</em> which is a way for them to verify who the authentication request is coming from and if it is valid. These are obtained from the site you are trying to implement authentication with, such as Github, and are unique to your app- <b>THEY ARE NOT TO BE SHARED</b> and should never be uploaded to a public repository or written directly in your code. A common practice is to put them in your <em>.env</em> file and reference them like: <code>process.env.GITHUB_CLIENT_ID</code>. For this challenge we're going to use the Github strategy.",
"Strategies with OAuth require you to have at least a <em>Client ID</em> and a <em>Client Secret</em> which is a way for them to verify who the authentication request is coming from and if it is valid. These are obtained from the site you are trying to implement authentication with, such as Github, and are unique to your app- <b>THEY ARE NOT TO BE SHARED</b> and should never be uploaded to a public repository or written directly in your code. A common practice is to put them in your <em>.env</em> file and reference them like: <code>process.env.GITHUB_CLIENT_ID</code>. For this challenge we're going to use the Github strategy.",
"Obtaining your <em>Client ID and Secret<em> from Github is done in your account profile settings under 'developer settings', then '<a href='https://github.com/settings/developers'>OAuth applications</a>'. Click 'Register a new application', name your app, paste in the url to your gomix homepage (<b>Not the project code's url</b>), and lastly for the callback url, paste in the same url as the homepage but with '/auth/github/callback' added on. This is where users will be redirected to for us to handle after authenticating on Github. Save the returned information as 'GITHUB_CLIENT_ID' and 'GITHUB_CLIENT_SECRET' in your .env file.",
"On your remixed project, create 2 routes accepting GET requests: /auth/github and /auth/github/callback. The first should only call passport to authenticate 'github' and the second should call passport to authenticate 'github' with a failure redirect to '/' and then if that is succesful redirect to '/profile' (similar to our last project).",
"On your remixed project, create 2 routes accepting GET requests: /auth/github and /auth/github/callback. The first should only call passport to authenticate 'github' and the second should call passport to authenticate 'github' with a failure redirect to '/' and then if that is successful redirect to '/profile' (similar to our last project).",
"An example of how '/auth/github/callback' should look is similar to how we handled a normal login in our last project: <pre>app.route('/login')\n .post(passport.authenticate('local', { failureRedirect: '/' }), (req,res) => { \n res.redirect('/profile'); \n });</pre>",
"Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point <a href='https://gist.github.com/JosephLivengood/28ea2cae7e1dc6a53d7f0c42d987313b'>here</a>."
],
@ -459,8 +459,8 @@
"title": "Implementation of Social Authentication II",
"description": [
"The last part of setting up your Github authentication is to create the strategy itself. For this, you will need to add the dependency of 'passport-github' to your project and require it as GithubStrategy like <code>const GitHubStrategy = require('passport-github').Strategy;</code>.",
"To set up the Github strategy, you have to tell <b>passport</b> to <b>use</b> an instantiated <b>GithubStrategy</b>, which accepts 2 arguments: An object (containing <em>clientID</em>, <em>clientSecret</em>, and <em>callbackURL</em>) and a function to be called when a user is successfully authenticated which we will determine if the user is new and what fields to save initially in the user's database object. This is common across many strategies but some may require more information as outlined in that specific stategy's github README; for example, Google requires a <em>scope</em> as well which determines what kind of information your request is asking returned and asks the user to approve such access. The current strategy we are implementing has its usage outlined <a>here</a>, but we're going through it all right here on freeCodeCamp!",
"Heres how your new strategy should look at this point: <pre>passport.use(new GitHubStrategy({\n clientID: process.env.GITHUB_CLIENT_ID,\n clientSecret: process.env.GITHUB_CLIENT_SECRET,\n callbackURL: /*INSERT CALLBACK URL ENTERED INTO GITHUB HERE*/\n },\n function(accessToken, refreshToken, profile, cb) {\n console.log(profile);\n //Database logic here with callback containing our user object\n }\n));</pre>",
"To set up the Github strategy, you have to tell <b>passport</b> to <b>use</b> an instantiated <b>GithubStrategy</b>, which accepts 2 arguments: An object (containing <em>clientID</em>, <em>clientSecret</em>, and <em>callbackURL</em>) and a function to be called when a user is successfully authenticated which we will determine if the user is new and what fields to save initially in the user's database object. This is common across many strategies but some may require more information as outlined in that specific strategy's github README; for example, Google requires a <em>scope</em> as well which determines what kind of information your request is asking returned and asks the user to approve such access. The current strategy we are implementing has its usage outlined <a>here</a>, but we're going through it all right here on freeCodeCamp!",
"Here's how your new strategy should look at this point: <pre>passport.use(new GitHubStrategy({\n clientID: process.env.GITHUB_CLIENT_ID,\n clientSecret: process.env.GITHUB_CLIENT_SECRET,\n callbackURL: /*INSERT CALLBACK URL ENTERED INTO GITHUB HERE*/\n },\n function(accessToken, refreshToken, profile, cb) {\n console.log(profile);\n //Database logic here with callback containing our user object\n }\n));</pre>",
"Your authentication won't be successful yet, and actually throw an error, without the database logic and callback, but it should log to your console your Github profile if you try it!",
"Submit your page when you think you've got it right."
],
@ -489,9 +489,9 @@
"id": "589a8eb3f9fc0f352b528e72",
"title": "Implementation of Social Authentication III",
"description": [
"The final part of the strategy is handling the profile returned from Github. We need to load the users database object if it exists or create one if it doesn't and populate the fields from the profile, then return the user's object. Github supplies us a unique <em>id</em> within each profile which we can use to search with to serialize the user with (already implemented). Below is an example imeplentation you can use in your project- it goes within the function that is the second argument for the new strategy, right below the <code>console.log(profile);</code> currently is:",
"The final part of the strategy is handling the profile returned from Github. We need to load the users database object if it exists or create one if it doesn't and populate the fields from the profile, then return the user's object. Github supplies us a unique <em>id</em> within each profile which we can use to search with to serialize the user with (already implemented). Below is an example implementation you can use in your project- it goes within the function that is the second argument for the new strategy, right below the <code>console.log(profile);</code> currently is:",
"<pre>db.collection('socialusers').findAndModify(\n {id: profile.id},\n {},\n {$setOnInsert:{\n id: profile.id,\n name: profile.displayName || 'John Doe',\n photo: profile.photos[0].value || '',\n email: profile.emails[0].value || 'No public email',\n created_on: new Date(),\n provider: profile.provider || ''\n },$set:{\n last_login: new Date()\n },$inc:{\n login_count: 1\n }},\n {upsert:true, new: true},\n (err, doc) => {\n return cb(null, doc.value);\n }\n);</pre>",
"With a findAndModify, it allows you to search for an object and update it, as well as upsert the object if it doesn't exist and recieve the new object back each time in our callback function. In this example, we always set the last_login as now, we always increment the login_count by 1, and only when we insert a new object(new user) do we populate the majority of the fields. Something to notice also is the use of default values. Sometimes a profile returned wont have all the information filled out or it will have been chosen by the user to remain private; so in this case we have to handle it to prevent an error.",
"With a findAndModify, it allows you to search for an object and update it, as well as upsert the object if it doesn't exist and receive the new object back each time in our callback function. In this example, we always set the last_login as now, we always increment the login_count by 1, and only when we insert a new object(new user) do we populate the majority of the fields. Something to notice also is the use of default values. Sometimes a profile returned won't have all the information filled out or it will have been chosen by the user to remain private; so in this case we have to handle it to prevent an error.",
"You should be able to login to your app now- try it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of this mini-project's finished code <a href='https://gomix.com/#!/project/guttural-birch'>here</a>."
],
"challengeSeed": [],
@ -762,4 +762,4 @@
]
}
]
}
}