Giter VIP home page Giter VIP logo

loopback-example-passport's Introduction

loopback-example-passport

⚠️ This LoopBack 3 example project is no longer maintained. Please refer to LoopBack 4 Examples instead. ⚠️

A tutorial for setting up a basic passport example.

Overview

LoopBack example for loopback-passport module. It demonstrates how to use LoopBack's user/userIdentity/userCredential models and passport to interact with other auth providers.

  • Log in or sign up to LoopBack using third party providers (aka social logins)
  • Link third party accounts with a LoopBack user (for example, a LoopBack user can have associated facebook/google accounts to retrieve pictures).

Prerequisites

Before starting this tutorial, make sure you have the following installed:

Client ids/secrets from third party

Tutorial - Facebook

1. Clone the application

$ git clone [email protected]:strongloop/loopback-example-passport.git
$ cd loopback-example-passport
$ npm install

2. Get your client ids/secrets from third party(social logins)

  • To get your app info: facebook
  • Click on My Apps, then on Add a new App
  • Pick the platform [iOS, Android, Facebook Canvas, Website]
  • Select proper category for your app.
  • Write your app name and "Site URL".
  • Skip the quick start to get your "App ID" and "App Secret", which is in "Settings"
  • Your app may not work if the settings are missing a contact email and/or "Site URL".
  • if you are testing locally, you can simply use localhost:[port#] as your "Site URL".

3. Create providers.json

  • Copy providers.json.template to providers.json

  • Update providers.json with your own values for clientID/clientSecret.

    "facebook-login": {
      "provider": "facebook",
      "module": "passport-facebook",
      "clientID": "xxxxxxxxxxxxxxx",
      "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "callbackURL": "/auth/facebook/callback",
      "authPath": "/auth/facebook",
      "callbackPath": "/auth/facebook/callback",
      "successRedirect": "/auth/account",
      "failureRedirect": "/login",
      "scope": ["email"],
      "failureFlash": true
    },
    "facebook-link": {
      "provider": "facebook",
      "module": "passport-facebook",
      "clientID": "xxxxxxxxxxxxxxx",
      "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "callbackURL": "/link/facebook/callback",
      "authPath": "/link/facebook",
      "callbackPath": "/link/facebook/callback",
      "successRedirect": "/auth/account",
      "failureRedirect": "/login",
      "scope": ["email", "user_likes"],
      "link": true,
      "failureFlash": true
    }
    

4. Facebook profile info

In a recent update, Facebook no longer returns all fields by default (email, gender, timezone, etc). If you need more information, modify the providers template.

The current template contains:

"profileFields": ["gender", "link", "locale", "name", "timezone", "verified", "email", "updated_time"],

We recommend modifying the fields to suit your needs. For more information regarding the providers template, see http://loopback.io/doc/en/lb2/Configuring-providers.json.html.

5. Data file

  • If you need to see your account info for testing purposes, in server\datasources.json, add:
"file":"db.json"

after

"connector": "memory",
  • The account info will be saved into this file.

6. Run the application

$ node .
  • Open your browser to http://localhost:3000
  • Click on 'Log in' (in the header, on the rigth)
  • Click on 'Login with Facebook'.
  • Sign up using a local account, then link to your Facebook account.

Tutorial - LDAP

1. Clone the application

Clone the application as describe above.

2. Create providers.json

  • Copy providers.json.template to providers.json
  • Update providers.json with your own values for profileAttributesFromLDAP and server section
  "ldap": {
    "provider": "ldap",
    "authScheme":"ldap",
    "module": "passport-ldapauth",
    "authPath": "/auth/ldap",
    "successRedirect": "/auth/account",
    "failureRedirect": "/ldap",
    "session": true,
    "failureFlash": true,
    "profileAttributesFromLDAP": {
      "login": "uid",
      "username": "uid",
      "displayName": "displayName",
      "email": "mail",
      "externalId": "uid"
    },
    "server":{
      "url": "ldap://ldap-server:1234",
      "searchBase": "dc=domain,dc=fr",
      "searchFilter": "(cn={{username}})"
    }
  },

Here, in profileAttributesFromLDAP section, we have configured the mapping to get

  • login, username and extranalIdfrom LDAP's uid,
  • displayNamefrom LDAP's displayName
  • emailfrom LDAP's mail

6. Run the application

$ node .
  • Open your browser to http://localhost:3000
  • Click on 'Log in' (in the header, on the rigth)
  • Click on 'Login with ldap account'
  • Enter credential from your LDAP account and click 'Submit' to see your LDAP data

More LoopBack examples

loopback-example-passport's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

loopback-example-passport's Issues

Can not use useridentity in Loopback-passport

Loopback-passport is awesome i think. i have looked through the example. i set it up with the following command
npm install loopback-component-passport

Now when i want to use the userIdentity as a base class i dont find it in the list. what is the problem. how can i make userIdentity and userCredential available that i can use them as a base class to create new.
Regards,
Refat.

/link/facebook 404 not found

From the Account page (/auth/account) there is a button for "Link Facebook." That button takes you to the /link/facebook page, which is a 404 page. How is this supposed to work?

Change in package.json for loopback-passport dependency breaks app

app.js requires 'loopback-passport' but the package.json file specifies loopback-component-passport.

Result when running:

module.js:340
throw err;
^
Error: Cannot find module 'loopback-passport'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object. (/Users/robbear/dev/github/loopback-example-passport/app.js:5:28)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)

Process finished with exit code 8

The model type must be a constructor

I'm trying to use the example code in this app in mine, but am running into this error

server-0 (err): AssertionError: The model type must be a constructor server-0 (err): at Function.registry.getModelByType (/usr/local/lib/node_modules/loopback/lib/registry.js:286:3) server-0 (err): at PassportConfigurator.setupModels (/usr/local/lib/node_modules/loopback-component-passport/lib/passport-configurator.js:33:70) server-0 (err): at Object.<anonymous> (/opt/nodegloo/server/server.js:71:22) server-0 (err): at Module._compile (module.js:456:26) server-0 (err): at Object.Module._extensions..js (module.js:474:10) server-0 (err): at Module.load (module.js:356:32) server-0 (err): at Function.Module._load (module.js:312:12) server-0 (err): at /usr/local/lib/node_modules/pm2/lib/ProcessContainer.js:187:23

this is in the passportConfigurator.setupModels() function

it seems when this is being called, app.models.user / userIdentity / userCredential are undefined and therefore causing the problem

Am I missing something, or is there a bug / mistake / setup problem ?

thanks

Getting error when accessing any of the methods through explorer ("Cannot call ACL.find(). The find method has not been setup. The PersistedModel has not been correctly attached to a DataSource!)

Just testing out of the box.

When trying any of the methods through localhost:3000/explorer I'm getting:

    {
      "error": {
        "name": "Error",
        "status": 500,
        "message": "Cannot call ACL.find(). The find method has not been setup. The PersistedModel has not been correctly attached to a DataSource!",
        "stack": "Error: Cannot call ACL.find(). The find method has not been setup. The PersistedModel has not been correctly attached to a DataSource!\n    at throwNotAttached (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/lib/models/persisted-model.js:63:9)\n    at Function.find (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/lib/models/persisted-model.js:168:3)\n    at Function.ACL.checkAccessForContext (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/lib/models/acl.js:397:8)\n    at Function.Model.checkAccess (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/lib/models/model.js:256:12)\n    at Function.<anonymous> (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/lib/application.js:319:13)\n    at execStack (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:344:11)\n    at RemoteObjects.execHooks (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:350:10)\n    at RemoteObjects.invokeMethodInContext (/home/geert-jan/sources/loopback-example-passport/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:472:8)\n    at /home/geert-jan/sources/loopback-example-passport/node_modules/loopback/node_modules/async/lib/async.js:610:21\n    at /home/geert-jan/sources/loopback-example-passport/node_modules/loopback/node_modules/async/lib/async.js:249:17"
      }
    }

I was expecting to get 401 instead.

I tried to check what the problem could be, but User etc are connected to datasource db which is correctly configured afaik. (I changed nothing at model-config.json and datasources.json)

btw:
client-secrets, etc. are configured correctly and the webapp appears to function correctly as well.

Anyone knows that's up?

loopback : 2.1.4
loopback-example-passport: 2.0.0

link.jade and linkAccounts.jade are missing

These templates have been deleted from the repo. I was able to retrieve them from the git history to get the pages to render. Were they deleted on purpose? The example project 404's without them.

Loopback Explorer 401

Sorry, still learning here, but I'm getting 401 from the loopback explorer with this project. Access Control is set to *, so I'm not sure the reason for the 401 response. What config is missing to enable it?

Adding LinkedIn - one key issue

OK so I added LinkedIn.

  1. First setup a LinkedIn account and lets put it in the providers.json file:
  "linkedin-login": {
    "provider": "linkedin",
    "module": "passport-linkedin-oauth2",
    "callbackURL": "http://localhost:3000/auth/linkedin/callback",
    "authPath": "/auth/linkedin",
    "callbackPath": "/auth/linkedin/callback",
    "successRedirect": "/auth/account",
    "clientID": "xxxxxxxxxxxxxxxxx",
    "clientSecret": "xxxxxxxxxxxxxxxxxx",
    "scope": ["r_basicprofile", "r_emailaddress", "r_network"],
    "state": true
  },
  1. Lets install the module:
    npm install https://github.com/dstroot/passport-linkedin-oauth2/raw/master/passport-linkedin-oauth2-1.1.2.tgz --save

This is a tweaked module because it needs a pull request that hasn't been merged yet: auth0/passport-linkedin-oauth2#19

  1. Let's add the login link:
<!DOCTYPE html>
<html>
<head>
    <title>Third Party Login</title>
</head>
<body>
<ul>
    <li><a href="/auth/facebook">Login with Facebook</a></li>
    <li><a href="/auth/google">Login with Google</a></li>
    <li><a href="/auth/twitter">Login with Twitter</a></li>
    <li><a href="/auth/linkedin">Login with LinkedIn</a></li>
</ul>
</body>
</html>
  1. ... and try it out. Weirdness ensues! It thinks it's Facebook!!! Yet at least some of the data is from LinkedIn. I've look at the "automagic" passport code and can't follow it to understand the error. Help!!!
My Account

LoopBack User

User Id: 1
User Name: facebook-login.dan.stroot
EMail: [email protected]
Third Party Profiles

[{"provider":"facebook-login","authScheme":"oAuth 2.0","externalId":"707798959","profile":
{"id":"707798959","username":"dan.stroot","displayName":"Dan Stroot","name":
{"familyName":"Stroot","givenName":"Dan"},"gender":"male","profileUrl":
"https://www.facebook.com/dan.stroot","emails":[{"value":"[email protected]"}],"provider":"facebook","_raw":"
{\"id\":\"707798959\",\"birthday\":\"04\\/11\\/1963\",\"email\":\"dan\\u0040thestroots.com\",\"first_name\":\"Dan\",\"gender\":\"male\",\"last_name\":\"Stroot\",\"link\":\"https:\\/\\/www.facebook.com\\/dan.stroot\",\"location\":{\"id\":\"109419232410281\",\"name\":\"Newport Beach, California\"},\"locale\":\"en_US\",\"name\":\"Dan Stroot\",\"timezone\":-8,\"updated_time\":\"2014-01-27T22:46:43+0000\",\"username\":\"dan.stroot\",\"verified\":true}","_json":{"id":"707798959","birthday":"04/11/1963","email":"[email protected]","first_name":"Dan","gender":"male","last_name":"Stroot","link":"https://www.facebook.com/dan.stroot","location":{"id":"109419232410281","name":"Newport Beach, California"},"locale":"en_US","name":"Dan Stroot","timezone":-8,"updated_time":"2014-01-27T22:46:43+0000","username":"dan.stroot","verified":true}},"credentials":{"accessToken":"CAADuMgSn9fMBAKkCZAv7OXOF5rRctYyVvdYgDeSogCO1HfPENp8cfAoxKsErcjqpJ8LZCqhpmQtV0TPh2Eaqt5MpDlDLPjxLi7Je0G6dQPJnjChPkV7ePUihi5o60dipXSYH13YwjnF2JXDLZBRCt5GGsez93xiyMAYw10YtTQodPZC7R1LRMpfExl0em4gspB5mbrJar0mnl8l1qW88"},"created":"2014-11-17T02:56:50.215Z","modified":"2014-11-17T03:10:16.090Z","id":1,"userId":1},{"provider":"linkedin-login","authScheme":"oAuth 2.0","externalId":"Sau1G1DIvq","profile":{"provider":"linkedin","id":"Sau1G1DIvq","displayName":"Daniel Stroot","name":{"familyName":"Stroot","givenName":"Daniel"},"emails":[{"value":"[email protected]"}],"_raw":"{\n \"apiStandardProfileRequest\": {\n \"headers\": {\n \"_total\": 1,\n \"values\": [{\n \"name\": \"x-li-auth-token\",\n \"value\": \"name:_1-Y\"\n }]\n },\n \"url\": \"https://api.linkedin.com/v1/people/Sau1G1DIvq\"\n },\n \"currentShare\": {\n \"author\": {\n \"firstName\": \"Daniel\",\n \"id\": \"Sau1G1DIvq\",\n \"lastName\": \"Stroot\"\n },\n \"comment\": \"Seems like the 1990's! Bill Gates' fortune grew by $15.8 billion in 2013 as Microsoft stock surged 35% http://buff.ly/1exr13F\",\n \"content\": {\n \"description\": \"From a financial standpoint, 2013 was a good year for Bill Gates.\",\n \"eyebrowUrl\": \"https://www.linkedin.com/share?viewLink=&sid=s5825310148557545474&url=http%3A%2F%2Fbuff%2Ely%2F194etCy&urlhash=rx91\",\n \"resolvedUrl\": \"http://www.geekwire.com/2014/top-bill-gates-named-worlds-richest-person/\",\n \"shortenedUrl\": \"http://buff.ly/194etCy\",\n \"submittedImageUrl\": \"http://www.geekwire.com/wp-content/uploads/gatesharvard212.png\",\n \"submittedUrl\": \"http://buff.ly/194etCy\",\n \"thumbnailUrl\": \"https://media.licdn.com/media-proxy/ext?w=80&h=100&hash=yiuqHj%2BjNC%2BakOi%2BoJW%2FeUJoiEw%3D&url=http%3A%2F%2Fwww.geekwire.com%2Fwp-content%2Fuploads%2Fgatesharvard212.png\",\n \"title\": \"Bill Gates' fortune grew by $15.8 billion in 2013 as Microsoft stock surged 35% - GeekWire\"\n },\n \"id\": \"s5825310148557545474\",\n \"source\": {\n \"application\": {\"name\": \"Buffer\"},\n \"serviceProvider\": {\"name\": \"LINKEDIN\"}\n },\n \"timestamp\": 1388862148000,\n \"visibility\": {\"code\": \"anyone\"}\n },\n \"distance\": 0,\n \"emailAddress\": \"[email protected]\",\n \"firstName\": \"Daniel\",\n \"formattedName\": \"Daniel Stroot\",\n \"headline\": \"Chief Information Officer at Allianz Global Investors\",\n \"id\": \"Sau1G1DIvq\",\n \"industry\": \"Investment Management\",\n \"lastName\": \"Stroot\",\n \"location\": {\n \"country\": {\"code\": \"us\"},\n \"name\": \"Orange County, California Area\"\n },\n \"numConnections\": 500,\n \"numConnectionsCapped\": true,\n \"pictureUrl\": \"https://media.licdn.com/mpr/mprx/0_TLYPQjuyZeG4z8Zq_kg8QYOP4HrNB8dqiGE2Qxj8FDXkeXONDimxH0Wm9QKwqbH486ySW4_ZNQRO\",\n \"positions\": {\"_total\": 0},\n \"publicProfileUrl\": \"https://www.linkedin.com/in/dstroot\",\n \"relationToViewer\": {\"distance\": 0},\n \"siteStandardProfileRequest\": {\"url\": \"https://www.linkedin.com/profile/view?id=4668759&authType=name&authToken=_1-Y&trk=api*a4158811*s4222991*\"},\n \"specialties\": \"Broad experience in the full array of information technology applications of an investment manager, including research, portfolio analysis and decision support, portfolio accounting and performance measurement, compliance, trade execution, and settlement.\\n\\nManagement skills include creating high performing teams, maintaining financial controls and objectives, creating and protecting intellectual property, creating relationships with strategic partners.\",\n \"summary\": \"Experienced technology executive (20+ years) in the Investment Management industry. Consistent, long term successes in technical leadership and strategy, systems architecture, implementation, and standards development and compliance.\"\n}","_json":{"apiStandardProfileRequest":{"headers":{"_total":1,"values":[{"name":"x-li-auth-token","value":"name:_1-Y"}]},"url":"https://api.linkedin.com/v1/people/Sau1G1DIvq"},"currentShare":{"author":{"firstName":"Daniel","id":"Sau1G1DIvq","lastName":"Stroot"},"comment":"Seems like the 1990's! Bill Gates' fortune grew by $15.8 billion in 2013 as Microsoft stock surged 35% http://buff.ly/1exr13F","content":{"description":"From a financial standpoint, 2013 was a good year for Bill Gates.","eyebrowUrl":"https://www.linkedin.com/share?viewLink=&sid=s5825310148557545474&url=http%3A%2F%2Fbuff%2Ely%2F194etCy&urlhash=rx91","resolvedUrl":"http://www.geekwire.com/2014/top-bill-gates-named-worlds-richest-person/","shortenedUrl":"http://buff.ly/194etCy","submittedImageUrl":"http://www.geekwire.com/wp-content/uploads/gatesharvard212.png","submittedUrl":"http://buff.ly/194etCy","thumbnailUrl":"https://media.licdn.com/media-proxy/ext?w=80&h=100&hash=yiuqHj%2BjNC%2BakOi%2BoJW%2FeUJoiEw%3D&url=http%3A%2F%2Fwww.geekwire.com%2Fwp-content%2Fuploads%2Fgatesharvard212.png","title":"Bill Gates' fortune grew by $15.8 billion in 2013 as Microsoft stock surged 35% - GeekWire"},"id":"s5825310148557545474","source":{"application":{"name":"Buffer"},"serviceProvider":{"name":"LINKEDIN"}},"timestamp":1388862148000,"visibility":{"code":"anyone"}},"distance":0,"emailAddress":"[email protected]","firstName":"Daniel","formattedName":"Daniel Stroot","headline":"Chief Information Officer at Allianz Global Investors","id":"Sau1G1DIvq","industry":"Investment Management","lastName":"Stroot","location":{"country":{"code":"us"},"name":"Orange County, California Area"},"numConnections":500,"numConnectionsCapped":true,"pictureUrl":"https://media.licdn.com/mpr/mprx/0_TLYPQjuyZeG4z8Zq_kg8QYOP4HrNB8dqiGE2Qxj8FDXkeXONDimxH0Wm9QKwqbH486ySW4_ZNQRO","positions":{"_total":0},"publicProfileUrl":"https://www.linkedin.com/in/dstroot","relationToViewer":{"distance":0},"siteStandardProfileRequest":{"url":"https://www.linkedin.com/profile/view?id=4668759&authType=name&authToken=_1-Y&trk=api*a4158811*s4222991*"},"specialties":"Broad experience in the full array of information technology applications of an investment manager, including research, portfolio analysis and decision support, portfolio accounting and performance measurement, compliance, trade execution, and settlement.\n\nManagement skills include creating high performing teams, maintaining financial controls and objectives, creating and protecting intellectual property, creating relationships with strategic partners.","summary":"Experienced technology executive (20+ years) in the Investment Management industry. Consistent, long term successes in technical leadership and strategy, systems architecture, implementation, and standards development and compliance."}},"credentials":{"accessToken":"AQXRiLcv9OF-BiPBDbonOFKmFhoTutu7hMyUVUSwh32p_1yoNoOI-3lgeTbuNN_Gcg9I6QoPueSlEf2TngJ4Rlvv75bWxTIWlh39KPxlVt23E4ZXMl-hD6hncGtioS1O57QXrHZ_ymLZiwGYy6m2Bp1LCYkkVPKQ8g6WvB84gI2D0nzo7DE"},"created":"2014-11-17T02:57:39.749Z","modified":"2014-11-17T03:07:39.551Z","id":4,"userId":1}]

Logout
Home

Available option for google auth: consent/select-account

In the providers.json file, there are some options you can pass down to passport's google auth stuff that can force getting consent again, or showing the account chooser. This might be of interest (it worked for me).

Specifically, you can add a line like this to providers.json for google-login

"authOptions":{"prompt": "args"},

where

args=consent: user will be prompted to allow app whatever permissions are implied by the "scope" parameter, even if they did so the last time they logged in

args=select_account: show the account chooser every time

supposedly, you can combine them, too:

args=select_account+consent

but this didn't work for me: probably because it escaped the "+" maybe you send an array there or something - I'll check the code

In my case, I couldn't figure out why it wasn't prompting me, and it was because I had logged into google in another window, and had logged into only one account.

This may be useful only in early development mode, but maybe there's a use-case where you want to intermittently get their consent again or something.

Reference (this is noted in the passport source code): http://stackoverflow.com/questions/14384354/force-google-account-chooser/14393492#14393492

local strategy

hey, first of all, great work with the framework, like the road you going :)

i am trying to set up the local strategy to work along side with the social logins,

after probing the code , i have set up the config as follow:

    "local": {
        "module": "passport-local",
        "provider": "local",
        "successRedirect": "/auth/account",
        "session": true
    }

then i tested it by adding a user to the db with the explorer... ( using the mongodb connector).
i have noticed that i have two "users" models differing by capital letters. ("Users", "users") but they both points to the same api url ("/api/Users").

i have tried to manually post the the "/api/users" path, but it's seems to be connected to the "User" model and not the "user" model...

i have also try to specify the collection name on the "users" model as follow:

"options": {
        "mongodb": {
            "collection": "users"
        }
    },

but it has no affect on the result, and the data keep's on going into the "Users" collection in the DB.

the social login work fine, tested it with facebook login but the data is located on the "users" collection...

i don't really understand the reason for re-create the user model (and others) with lower casing and i guess i will need to dive in to figure the overall solution..

is there a fix for this coming soon? is there an architectural problem that i should be aware of?

thx,
elior

Use 3rd party access token to protect access to API

I have the sample up and working with Facebook, and can secure pages by applying the 'ensureLoggedIn' middleware - but I'm not sure how to secure APIs with the same authentication mechanism.

For example, I have an api (/api/people) that uses the rest datasource to call a REST endpoint running on a different server. I would like to allow access to only if the caller presents an oAuth token with the Facebook access_token and, ideally, that token should be passed through to the back end API as part of the call.

Hope this makes sense!

Page 'pages/linkedAccounts' missing from sample

In server/server.js there is a method

app.get('/link/account', ensureLoggedIn('/login'), function (req, res, next) {
  res.render('pages/linkedAccounts', {
    user: req.user,
    url: req.url
  });
});

which refers to 'pages/linkedAccounts'. This page doesn't exist in server/views/pages.

When you click 'Link with Facebook/Google' button on the accounts page you get the following error:

Error: Failed to lookup view "pages/linkedAccounts" in views directory "/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/server/views" at EventEmitter.render (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/application.js:579:17) at ServerResponse.render (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/response.js:961:7) at ServerResponse.res.render (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/express-flash/lib/express-flash.js:29:16) at /Users/danielfitzgerald/Documents/workspace/loopback-example-passport/server/server.js:97:7 at Layer.handle [as handle_request] (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/router/layer.js:95:5) at next (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/router/route.js:131:13) at /Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/connect-ensure-login/lib/ensureLoggedIn.js:50:5 at Layer.handle [as handle_request] (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/router/layer.js:95:5) at next (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/router/route.js:131:13) at Route.dispatch (/Users/danielfitzgerald/Documents/workspace/loopback-example-passport/node_modules/loopback/node_modules/express/lib/router/route.js:112:3)

Loopback 2.0 compatibility

I'm working to add this to a 2.0 project and when I'm following the example code in this project, I'm getting the error:

Error: Model not found: UserCredential

Running with debug I get:

5 Aug 20:28:17 - [nodemon] v1.2.1
5 Aug 20:28:17 - [nodemon] to restart at any time, enter `rs`
5 Aug 20:28:17 - [nodemon] watching: *.*
5 Aug 20:28:17 - [nodemon] starting `node server/server.js`
  loopback:boot:executor Configuring existing model User +0ms
  loopback:boot:executor Configuring existing model AccessToken +5ms
  loopback:boot:executor Configuring existing model ACL +1ms
  loopback:boot:executor Configuring existing model RoleMapping +0ms
  loopback:boot:executor Configuring existing model Role +0ms
  loopback:boot:executor Creating new model user {"name":"user","plural":"users","base":"User","properties":{"accessTokens":{"type":"hasMany","model":"accessToken","foreignKey":"userId"},"identities":{"type":"hasMany","model":"userIdentity","foreignKey":"userId"},"credentials":{"type":"hasMany","model":"userCredential","foreignKey":"userId"}},"validations":[],"relations":{},"acls":[],"methods":[]} +1ms
  loopback:boot:executor Creating new model userCredential {"name":"userCredential","plural":"userCredentials","base":"UserCredential","properties":{},"validations":[],"relations":{"user":{"type":"belongsTo","model":"user","foreignKey":"userId"}},"acls":[],"methods":[]} +5ms

/Users/collin/code/backend/node_modules/loopback/lib/registry.js:202
  throw new Error('Model not found: ' + modelName);
        ^
Error: Model not found: UserCredential
    at Function.registry.getModel (/Users/collin/code/backend/node_modules/loopback/lib/registry.js:202:9)
    at Function.registry.createModel (/Users/collin/code/backend/node_modules/loopback/lib/registry.js:102:22)
    at /Users/collin/code/backend/node_modules/loopback-boot/lib/executor.js:153:28
    at Array.forEach (native)
    at defineModels (/Users/collin/code/backend/node_modules/loopback-boot/lib/executor.js:141:23)
    at setupModels (/Users/collin/code/backend/node_modules/loopback-boot/lib/executor.js:130:3)
    at execute (/Users/collin/code/backend/node_modules/loopback-boot/lib/executor.js:25:3)
    at bootLoopBackApp (/Users/collin/code/backend/node_modules/loopback-boot/index.js:79:3)
    at Object.<anonymous> (/Users/collin/code/backend/server/server.js:17:1)
    at Module._compile (module.js:456:26)
5 Aug 20:28:20 - [nodemon] app crashed - waiting for file changes before starting...

I was able to change the model definitions from the 1.x format to 2.0 but I'm guessing there is still something I'm missing as far as getting loopback to inherit the models that this project includes?

It is hard to use this loopback-example-passport because ...

... I think the structure of the slc loopback default app has changed since the writing of this.

Currently, I am trying to find out how passport parts should be placed in the current slc loopback app.

I feel that ../boot/.js should be used instead of placing all the passport components in server.js

how to get the accessToken?

Having a hell of a time figuring out how to get the accessToken so after my user is authenticated I can hit the api and do stuff. Tried:

    console.log('Token: ' + req.accessToken);

    if (req.headers && req.headers.access_token) {
      tokenId = req.headers.access_token;
      console.log('Token: ' + tokenId);
    }

    var AccessToken = app.models.AccessToken;
    AccessToken.findForRequest(req, {}, function (err, token) {
      if (err) {
        req.flash('error', { msg: 'Sorry, something went wrong! ' + err.message });
        return res.redirect('back');
      }
      console.log('Token: ' + token);
    });

how to add workflow?

Say I wanted to send a welcome email after a person signs up for the first time. Where/how is the best place and method to do so? Could someone just point me in the right direction?

Profile as a Model would be beneficial

It would be beneficial to have Profile as a proper Model within the Passport Example.

Two main reasons ...

  1. When using a database for persistence the default size when migrating the schema is 1024 char. When you receive the profile data this is typically larger than the default field size, thus causing an error.
  2. Showing the configurations in the provider.json for Profile demonstrates some of the available data from providers.

Proposal would be ...

  1. update providers to include
    "scope": ["email", "profile"],
    "profileFields": [ "id", "emails", "displayName", "last_name", "first_name", "gender", "age_range", "link", "photos", "timezone", "is_verified" ] etc...
  2. Provide profile Model to contain the above fields
  3. On create of new user also create the profile with available data returned from provider.
  4. Update signup page for local account to include optional profile fields.

Thoughts?

Say I wanted to timestamp the user's logins?

Example:

Each time a user logs in I want to timestamp the event on the user record. In a separate process I may send emails to users who haven't visited in a while.

Where is the passport login process can I add a hook to timestamp the user's record? Just point me the right direction please.

ldap configuration

I am trying to configure passport for authentication with an ldap provider using passport-ldapauth
"ldap": {
"provider": "ldap",
"authScheme":"ldap",
"module": "passport-ldapauth",
"authPath": "/auth/ldap",
"server":{
"url": "ldap://server:10389/o=org,dc=domain,dc=com",
"adminDn": "uid=admin,ou=system",
"adminPassword": "pwd",
"searchBase": "ou=users,o=org,dc=domain,dc=com",
"searchFilter": "(cn={{username}})"
}
}

Everything seems to be working fine until the point where done(err, user, authInfo) is called inside loginCallback(req, done) defined in passport-configurator.js.

TypeError: undefined is not a function

Where is the done closure supposed to be defined?

Thanks for your help!

Update to documentation: Facebook profile info via providers.json

I followed one of the tutorials and the Stopwatch example.
https://github.com/vkarpov15/stopwatch-server-example/
https://github.com/vkarpov15/stopwatch-example

The documentation does not seem to have the crucial info that changing the providers.json scope and profileFields can provide more information from Facebook.

I experimented with it to find it out, so I thought I'd just add it in here. The profile info shows up under the UserIdentity model.

   "scope": ["public_profile","email","user_birthday"],
    "profileFields":["id","displayName","gender","email","age_range","photos","birthday"]
}

It mentions it here https://docs.strongloop.com/display/LB/Tutorial%3A+third-party+login
but it is a little vague and suggests changing the JavaScript of the module, which was unnecessary for me.

Question on providers.json.template

Except for "local strategy" all other providers x-login and x-link section in the template. What is the meaning of that and where can I read more about it?

Proper profile model to store fields returned from Facebook, Google, etc....

There should be a proper profile model with relationship to user. If you provide profileFields suggested by passport within the providers.json, then these fields should be stored in a profile model. Developers can then have the chance to extend this model to suit their needs.

If you currently use a relational DB such as Postgres there will be an error due to profile field default length not large enough for the default field size as current implementation has all profile fields stored in single field.

I have implemented a hook after user create but I think it would be cleaner to have as part of the implementation of module.

Configure strategy in providers error

I see that commits are as recent as a few minutes ago, so I apologize if I'm jumping on something that's still a WIP, however, just figured I would document an issue I ran into: as of this commit running npm start complains that providers.json.template does not have a passport strategy configured.

full output:

Brians-MacBook-Pro:passport-strongloop-test brianfeister$ npm start

> [email protected] start /Users/brianfeister/dev/passport-strongloop-test
> node app.js

connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0
Please configure your passport strategy in providers.json.
Use providers.json.template as the template.

npm ERR! [email protected] start: `node app.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] start script.
npm ERR! This is most likely a problem with the loopback-example-passport package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node app.js
npm ERR! You can get their info via:
npm ERR!     npm owner ls loopback-example-passport
npm ERR! There is likely additional logging output above.
npm ERR! System Darwin 12.5.0
npm ERR! command "/usr/local/Cellar/node/0.10.26/bin/node" "/usr/local/bin/npm" "start"
npm ERR! cwd /Users/brianfeister/dev/passport-strongloop-test
npm ERR! node -v v0.10.26
npm ERR! npm -v 1.4.3
npm ERR! code ELIFECYCLE
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /Users/brianfeister/dev/passport-strongloop-test/npm-debug.log
npm ERR! not ok code 0
Brians-MacBook-Pro:passport-strongloop-test brianfeister$ 

Need clarification - inconsistencies

@raymondfeng The example models.json has all core loopback models redeclared with a lowercased model name, and then pointing to the actual base model. Why this differentiation? Wouldn't you be able to extend the core models otherwise? Note that:

loopback.getModel('user') !== loopback.getModel('User') whereas:

loopback.models.user === loopback.models.User

due to how the model name is normalized in several ways. This is bad practice IMHO - we need to be more explicit and it would help if there was a recommended naming scheme.

User afterRemote('create' not firing after adding passport

I added a user.js file to this project and an email DS, etc. When I add some functionality for lost password, reset, etc. it works. When I try to add email verification to this app, it fails and the remote hook never gets fired.

Is there any reason why User.create is not working during signup when the User.create(newUser, ... is in the signup route and I add remote hook? Since user.json extends User model in core, do we have to somehow register the create remote method?

Added email verification from the loopback-faq-user-management example app and User.afterRemote('create' fails

var path = require('path');
var app = require(path.resolve(__dirname, '../../server/server'));

module.exports = function(user) {
  //send verification email after registration
  user.afterRemote('create', function(context, user, next) {
    console.log('> user.afterRemote triggered');

    var options = {
      type: 'email',
      to: user.email,
      from: '[email protected]',
      subject: 'Thanks for registering.',
      template: path.resolve(__dirname, '../../server/views/pages/verify.jade'),
      redirect: 'pages/verified',
      user: user
    };

    user.verify(options, function(err, response) {
      if (err) {
        next(err);
        return;
      }

      console.log('> verification email sent:', response);

      context.res.render('pages/response', {
        title: 'Signed up successfully',
        content: 'Please check your email and click on the verification link '
          + 'before logging in.',
        redirectTo: '/',
        redirectToLinkText: 'Log in'
      });
    });
  });

  //send password reset link when requested
  user.on('resetPasswordRequest', function(info) {
    var url = 'http://' + app.get('email_link_domain') + '/reset-password';
    var html = 'Click <a href="' + url + '?access_token=' + info.accessToken.id
      + '">here</a> to reset your password';

    user.app.models.Email.send({
      to: info.email,
      from: info.email,
      subject: 'Password reset',
      html: html
    }, function(err) {
      if (err) return console.log('> error sending password reset email');
      console.log('> sending password reset email to:', info.email);
    });
  });
};

loopbackPassport in router.js inside boot

Hi I'm new in Loopback. I was trying to move the passport dependencies from server.js to a new file router.js inside ./boot but in this file passport doesn't create a new user.

Missing page

500 Error: Failed to lookup view "pages/link" in views directory

The Jade page does not exist

Facebook no longer returns all fields by default

More of a heads up for anyone coming across this.

New Apps created in facebook automatically get v2.4 + Graph API and both versioned/unversioned requests are upgraded to 2.4.

Hence:
https://graph.facebook.com/v2.2/me with ClientID/ClientSecret from a new app returns ONLY id + name. Even though it's versioned it uses v2.4+)

In order to return to the old behaviour and get the same fields we need to explicitly call

https://graph.facebook.com/v2.2/me?fields=first_name,gender,last_name,link,locale,name,timezone,verified,email,updated_time

This is possible with the profileFields field in the AuthStrategy options.

So providers.json.template should include:

"profileFields": ["gender","link","locale","name","timezone","verified","email","updated_time"],

for the facebook-login provider to function as expected

Passport login does not set req.accessToken

Other LB apps leverage the User.login() which returns an accessToken and also set in the request. This token is then used for subsequent requests to API, etc. In this example app since it uses Passport's req.login() it bypasses LB's built in accessToken to leverage the ACL and Roles (RBAC).

What is the best way to incorporate Passport, but also include LB's built in user model and RBAC? Is there some remote hook after login with passport (local or social strategies) that we can then do additional logic?

loopback.getCurrentContext() returns empty {} for "active"

Extending this example to have an "Events" model I have this js

var loopback = require('loopback');
module.exports = function(Event) {

  Event.observe('before save', function (ctx,next) {
    
    var context = loopback.getCurrentContext();
    console.log('context:', context.active);
    next();
  });

};

The console shows an empty {}

Doing some testing I think it has somethign to do with this:

app.middleware('auth', loopback.token({
  model: app.models.AccessToken
}));

Cannot GET /auth/facebook

I deployed to AWS so that Facebook would have an URL to callback to, but, when Facebook did so it console logs:

Error: Cannot GET /auth/facebook

Current build isn't working

After npm install succeeeds, I run node and get an error:

/login-sample/loopback-example-passport/server/server.js:180
      console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
                                                  ^
ReferenceError: baseUrl is not defined
    at Server.<anonymous> (/Users/pol/Dev/ilp/login-sample/loopback-example-passport/server/server.js:180:51)
    at Server.g (events.js:199:16)
    at Server.emit (events.js:129:20)
    at net.js:1171:12
    at process._tickDomainCallback (node.js:381:11)
    at process.<anonymous> (/Users/pol/Dev/ilp/login-sample/loopback-example-passport/node_modules/async-listener/index.js:19:15)
    at Function.Module.runMain (module.js:503:11)
    at startup (node.js:129:16)
    at node.js:814:3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.