Closed zhouhao27 closed 5 years ago
By going through the source code for ParseUser testing code, I'm wondering do we need to write the Provider by ourselves?
Here's for a sample provider for Facebook:
@flovilmart Thanks for your code. But I'm a bit confusing about this part. I'm wondering where the code for login to FB is in server side or client side? If it's in client side then we can call FB SDK directly without using parse-sdk-js, am I right?
And I saw some codes in authDataManager, what's this for ?
Can anybody explain the workflow of oauth (client side and server side), take Facebook as an example?
@benitech Agree with you. A sample will be a great help.
I'm struggling here as well...
On the server I've configured the twitter oauth module as explained in the docs:
var parseApi = new ParseServer({
...
oauth: {
instagram: {} // From what I can see in the src, no options needed
},
...
And on the JS Client side I'm trying to login like this (after getting an auth_token from instagram):
// Create a instagram provider
var provider = {
authenticate(options) {
if (options.success) {
options.success(this, {
auth_token: 'MY_AUTH_TOKEN'
});
}
},
restoreAuthentication(authData) {},
getAuthType() {
return 'instagram';
},
deauthenticate() {}
};
// Login the user with the instagram provider
var user = new Parse.User();
Parse.User.logInWith(provider, {}).then((user) => {
console.log(user);
}, (error) => {
console.log(error);
});
But I'm always getting back a 400 error:
ParseError {code: 252, message: "This authentication method is unsupported."}
If you remove Instagram from your Oauth hash in your config? What's it doing?
Le 8 avr. 2016 10:19 -0400, flavordaaavenotifications@github.com, a écrit :
I'm struggling here as well...
On the server I've configured the twitter oauth module as explained in the docs:
var parseApi = new ParseServer({ ... oauth: { instagram: {} // From what I can see in the src, no options needed }, ...
And on the JS Client side I'm trying to login like this (after getting an auth_token from instagram):
// Create a instagram provider var provider = { authenticate(options) { if (options.success) { options.success(this, { auth_token: 'MY_AUTH_TOKEN' }); } }, restoreAuthentication(authData) {}, getAuthType() { return 'instagram'; }, deauthenticate() {} }; // Login the user with the instagram provider var user = new Parse.User(); Parse.User.logInWith(provider, {}).then((user) =>{ console.log(user); }, (error) =>{ console.log(error); });
But I'm always getting back a 400 error:
ParseError {code: 252, message: "This authentication method is unsupported."}
— You are receiving this because you were mentioned. Reply to this email directly orview it on GitHub(https://github.com/ParsePlatform/Parse-SDK-JS/issues/246#issuecomment-207449657)
You mean removing the whole
oauth: {
instagram: {} // From what I can see in the src, no options needed
},
thing in the Parse Server configuration? Then I get exactly the same error...
Can you gimme the logs from your login attempt when running with env VERBOSE=1
verbose: POST /api/users { host: 'localhost:1337',
connection: 'keep-alive',
'content-length': '186',
origin: 'http://evil.com/',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
'content-type': 'text/plain',
accept: '*/*',
referer: 'http://localhost:8100/',
'accept-encoding': 'gzip, deflate',
'accept-language': 'en' } {
"authData": {
"instagram": {
"auth_token": "MY_AUTH_TOKEN"
}
}
}
verbose: error: code=252, message=This authentication method is unsupported.
(I'm currently running the server AND my JavaScript App locally)
I finally managed to get it working. I was missing the auth_data object which requires the ID. Here's my sample code:
// Create a instagram provider
var provider = {
authenticate(options) {
if (options.success) {
options.success(this, {});
}
},
restoreAuthentication(authData) {},
getAuthType() {
return 'instagram';
},
deauthenticate() {}
};
// Create the authData object
let authData = {
authData: {
auth_token: 'MY_AUTH_TOKEN',
id: 123456 // IMPORTANT: This key is a must because pare-server checks for it
}
}
// Login the user with the instagram provider
var user = new Parse.User();
Parse.User.logInWith(provider, authData).then(user => {
console.log(user);
}, error => {
console.log(ErrorConstructor);
});
Hi, would it be possible for you to break the code down into a server side and a client side part, so it is easier for other devs struggling with similar implementation. More like "Parse oAuth for Dummies" tutorial would be great.
As in - This is what you do on the server side in this "file"(/cloud/main.js or different?). This is where you add the keys and start Parse Server. And this is what you do on the client side SDK.
You would save a lot of people a lot of effort.
Thanks.
@benitech The complete snippet above is client side. On the server side the only thing you need to do is configure parse-server to use your preferred oauth module (only possible with the open source parse server). In my case I just use instagram as already noted further above:
var parseApi = new ParseServer({
...
oauth: {
instagram: {}
},
...
That's all.
@flavordaaave Where do you get the id
and auth_token
?
@zhouhao27 Those you need to get on client side (e.g. using hellojs). Depending on what oauth provider you choose, you might need some different keys sent with the authData
object. For instance the instagram providers needs to get an access_token
besides the ID (NOT auth_token
, I had this wrong in my previous posts) .
@flavordaaave thanks, your example make it much clearer for me now.
Quite agree with @benitech, the document is so unclear and without a good example of the workflow, I thought the OAuth was implementing from the server-side and so the configuration in here makes no sense to me.
@flavordaaave do you have any idea that if I can store the access_token passed to the server to be stored elsewhere for the user by myself?
I think if we make the OAuth implemented on the server-side it will be much clearer for both sides.
The server side can perform different OAuth types using plugins. And the client side doesn't need to worries about much of the difference between OAuth workflows, the only thing client side SDK need to implement is just a generic OAuth login workflow ( some generic UI, like open a new window for login ).
You're free to implement Oauth serverside, but most of the client SDK offer a seamless, clientside Authenticaton flow, which is better than the server danses, as well as implementing all different token formats, id fetch etc...
We'll consider a PR on parse-server for that.
Another benefit of client side OAuth is that it works wether you're developing on the simulator, localhost etc, without changing the server redirect or the provider configuration.
@neekey i feel the current implementation is quite proper from a security standpoint, though it would have helped if there was some initial documentation to begin with.
You will note that even in JS, the most popular NodeJS Auth library - PassportJS - does not have a proper social oauth with JWT token implementation.
Also as i mentioned in this comment to your question (https://github.com/ParsePlatform/parse-server/issues/2106#issuecomment-227090113), this is all you need to implement it both server and client side.
Definitely still needs cleaner docs.
@flovilmart I think you got a point about the benefit for Client OAuth, I haven't thought about that.
@benitech For security concern, I think client side of OAuth is apparently worse than server side since you have to pass your "access_token" through the network. And some of the Platform like LinkedIn and Github, they support only OAuth1 or OAuth2 with Explicit Grant, the authentication flow needs to be signed with a secret key that may not be exposed in the browser. The popular client-side OAuth library HelloJS gets around this problem by using their proxy server, which means you need to sign up your application info into its server, I am not doubting the author's intention, but relying on another server to implement an OAuth sounds just not good.
And I don't think implementing an Auth process on server will be a problem, it's not perfect for PassportJS to do this is maybe because it wants to cover all the platforms.
Anyway, just some basic thoughts about this issue, quite new here, will learn more about parse-server : )
@neekey the main purpose of the server side implementation is to re-authenticate the "token" and do seamless integration into Parse SDK functions. Sending token etc is immaterial cos of https.
You may be right. I just have not seen a better implementation yet that works across iOS, Android and JS(?).
EDIT: My comments are solely based on the Android /iOS implementation. For JS, yes, it should definitely be server side ONLY.
As an example, using @flovilmart 's gist for iOS Twitter implementation and using Fabric.io SDK plugin, you could have the Twitter oauth working both client / server side in less than 30 mins.
The oAuth process is split in 2 parts,
At this time, I don't believe this is the responsibility of the client SDK, nor parse-server to acquire this token. The second part, is already implemented and it makes sense for many reasons to keep it that way.
On the 1st part, as many of you mention, passport is doing a great job at it, and not all oAuth require serverside redirects. Having the auth_token in the client is no more insecure than basic authentication. He insecure part is storing that token in clear in mongo, but we don't have much choice here as this token is not only used for identity verification but also interacting with the services.
I agree that the documentation for the client side auth handling could be better, the gist I provided could be improved, but implementing passport in parse-server don't seem to be the right solution at that time as you can very easily integrate it if you need it.
That being said, I'm all open for improvements.
PS: In the past 5 years, I've build many social logins, and never relied on passport to do so, implementing a generic serverside oAuth handler is pretty straightforward.
So you can (currently) use loginWith for anything auth aside from Facebook right now?
@AndrewLane you can use any of the following or create your own.
https://github.com/ParsePlatform/parse-server/tree/master/src/authDataManager
Thanks. Does unlink work? I was having success with link but not unlink.
On Thursday, August 4, 2016, benitech notifications@github.com wrote:
@AndrewLane https://github.com/AndrewLane you can use any of the following or create your own.
https://github.com/ParsePlatform/parse-server/tree/master/src/ authDataManager
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ParsePlatform/Parse-SDK-JS/issues/246#issuecomment-237743887, or mute the thread https://github.com/notifications/unsubscribe-auth/AAdQAGnwwLAXt9CrMOVLXZzU-FlYurqNks5qcqfigaJpZM4H7cBk .
This is still not clear at all. How do we have to use loginWith together with Twitter, Google etc. On the server-side there are several oauth managers (https://github.com/ParsePlatform/parse-server/wiki/OAuth) which seem to do the required work. On the client-side the only documented and available methods are focussed on Facebook (e.g. FacebookUtils), but there are no pointers on how to use other services.
What are the exact steps on the client-side using the SDK to login with other services? Why is there no TwitterUtils for example?
@jonas-db Did you find any solution for other services?
@junal I ended up using hello.js (https://adodson.com/hello.js/) to obtain a token from the specific provider (Twitter, Google, etc) and passed that auth_token and auth_token_secret to
Parse.User.logInWith(twitterProvider, { authData : authData })
where twitterProvider is an instance of:
export default {
authenticate(options) {
if (options.success) {
options.success(this, {});
}
},
restoreAuthentication(authData) {
console.log(arguments)
},
getAuthType() {
return 'twitter';
},
deauthenticate() {}
};
Hope it helps
@jonas-db that's a very nice solution, can you make a PR on the docs repository as an example on the JS docs? That could be slick
@jonas-db @flovilmart Thank you so much! Here's my full code. I'm getting "This authentication method is unsupported." error. Where am I making mistake?
var accessToken = "....";
var id = "....";
var provider = {
authenticate(options) {
if (options.success) {
options.success(this, {});
}
},
restoreAuthentication(authData) {},
getAuthType() {
return 'facebook';
},
deauthenticate() {}
};
let authData = {
authData: {
id: id,
access_token: accessToken
}
};
Parse.User.logInWith(provider, authData).done(function (result) {
console.log(result);
}).fail(function (error) {
console.log(error);
});
Hi @junal i was able to get your code snippet working by setting: options.success(this, {})
to options.success(this, authData)
also i set the username to instagram username to prevent random username from being set to new users
var accessToken = "....";
var id = "....";
var username="...."; // instagram username
let authData = {
authData: {
id: id,
access_token: accessToken
}
};
var provider = {
authenticate(options) {
if (options.success) {
options.success(this, authData);
}
},
restoreAuthentication(authData) {},
getAuthType() {
return 'instagram';
},
deauthenticate() {}
};
let user = new Parse.User();
user.set("username", username);
user.logInWith(provider, authData).done(function (result) {
console.log(result);
}).fail(function (error) {
console.log(error);
});
parse config:
var parseApi = new ParseServer({
...
oauth: {
instagram: {}
},
...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I'd like to use third party login, for example, Facebook, Twitter. But not very sure how to call logInWith function. For example, my code:
But got the following error:
My other Parse function works fine. I'm using 1.8.1 JavaScript SDK.