We’ve been using the following code for 3rd party auth via AD for a long time without issues, however, upgrading from v4.10.3
> v5.2.5
breaks the linkWith
function, which historically returned a sessionToken (as documented here: JavaScript Developers Guide | Parse .
let ssoUser = new Parse.User({
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email.toLowerCase(),
username: userData.email.toLowerCase(),
});
ssoUser = await ssoUser.linkWith(
'microsoft',
{ authData: authData.microsoft },
{ useMasterKey: true }
);
console.log(ssoUser.getSessionToken()) // undefined
Any suggestions are welcome, thank you.
I guess the problem is happening because you are using the { useMasterKey: true }
option. Could you please try without it?
Hi @davimacedo , unfortunately not. first I got the error Clients aren't allowed to manually update email verification
. So I commented out the emailVerified: true,
section, and got the same behaviour - no session token returned from the linkWith
function.
Any other thoughts would be very welcome.
Cheers
Maybe you found a bug. Would you be willed to open a PR to the Parse Server project with a failing test case?
More than willing to do that, once I have figured out how. Leave it with me.
Hi @davimacedo I was unable to get the test case to fail, so I have been checking all the differences in my update branch and came across the change in 5.x
, which makes directAccess: true
by default. I changed this to false in the parse config object and everything miraculously works perfectly.
I’ve been reading up a little on the directAccess
changes and I’m not sure I fully understand it, and unsure how much of a performance hit I will have by turning it off (I guess not a hit, but no improvement from 4 > 5).
Do you think there is scope for me to make an improvement to the tests / codebase with this finding, or is it just down to my unique implementation?
It can be something unique to your implementation. Since the directAccess option is making difference on how your code behaves, I assume this code is actually a cloud code function, right? Would you mind to share the cloud code function that you have in place for that?
Sure,
Here is the code:
async LoginUser(request) {
let user;
const { username, password, installationId, authData } =
request.params;
// If this is an SSO login, it will send { authData: { microsoft: { id, access_token } } }
if (authData && authData.microsoft) {
// for now we only support microsoft
const msalProfile = await getMsalProfile(authData.microsoft.access_token);
let firstName = msalProfile.givenName;
let lastName = msalProfile.surname;
const userData = {
firstName,
lastName,
email: msalProfile.mail || msalProfile.userPrincipalName,
profession: msalProfile.jobTitle,
};
let ssoUser = new Parse.User({
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email.toLowerCase(),
username: userData.email.toLowerCase(),
profession: userData.profession,
emailVerified: true,
isSSO: true,
});
ssoUser = await ssoUser.linkWith(
'microsoft',
{ authData: authData.microsoft },
{ useMasterKey: true }
);
user = ssoUser;
} else {
// Otherwise, this is a username/password login so we proceed as normal
const userQuery = new Parse.Query(Parse.User).equalTo(
'username',
username
);
user = await Parse.User.logIn(username, password, { installationId });
}
return user;
}
Is it a trigger or cloud function?
I still believe that it should return the session token without using the useMasterKey option and even from cloud code using directAccess option. Maybe it is a bug on the directAccess option. If you could try once more to write a failing test case in parse server in which you have this option set true and see if you can reproduce. Another idea would be trying something like this:
let ssoUser = new Parse.User({
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email.toLowerCase(),
username: userData.email.toLowerCase(),
profession: userData.profession,
emailVerified: true,
isSSO: true,
authData
});
await ssoUser.save();
Manuel
October 12, 2022, 7:39pm
12
I just tried it out with the REST API with PUT
to endpoint <parse-server-url>/users
and body:
{
"authData": {
"facebook": {
"id": "...",
"access_token": "...",
"expiration_date": "..."
}
}
}
The sign-up was successful and the response included the session token. Parse Server 5.2.7
I suggest you also try it with the REST API, as it cuts out the Parse JS SDK and lets you determine whether there is an issue with the server.
You cannot set some of the values on the _User
without using masterkey, emailVerified
for example.
I will take a look at what Manuel suggested and see how I get on.
Manuel
October 12, 2022, 8:32pm
14
The default is not true
in Parse Server 5, it’s still false
. The PR you referenced only officially deprecated the default state. The default is scheduled to change from false
to true
in Parse Server 6.
You cannot set some of the values on the _User
without using masterkey, emailVerified
for example.
Which values are these? That would be good to know, so maybe try one by one and see which one(s) you cannot set.
cbaker6
October 12, 2022, 10:37pm
15
Sounds like it could be similar to an issue that occurred with the Swift SDK:
opened 02:20PM - 01 Apr 21 UTC
closed 09:27AM - 02 Apr 21 UTC
type:bug
I see a parse JsonDecoder error:
```
ParseError code=-1 error=Error decoding… parse-server response: Optional(<NSHTTPURLResponse: 0x6000006e84c0> { URL: https://podlive-parse-server.herokuapp.com/parse/users/jXjF1qjJhw } { Status Code: 200, Headers {
"Access-Control-Allow-Headers" = (
"X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-Parse-Request-Id, Content-Type, Pragma, Cache-Control"
);
"Access-Control-Allow-Methods" = (
"GET,PUT,POST,DELETE,OPTIONS"
);
"Access-Control-Allow-Origin" = (
"*"
);
"Access-Control-Expose-Headers" = (
"X-Parse-Job-Status-Id, X-Parse-Push-Status-Id"
);
Connection = (
"keep-alive"
);
"Content-Length" = (
40
);
"Content-Type" = (
"application/json; charset=utf-8"
);
Date = (
"Thu, 01 Apr 2021 13:24:07 GMT"
);
Etag = (
"W/\"28-69gFBc5Q54gsdpFK0tjSk36K+Xc\""
);
Server = (
Cowboy
);
Via = (
"1.1 vegur"
);
"X-Powered-By" = (
Express
);
} }) with error: Die Daten konnten nicht gelesen werden, da sie fehlen. Format: Optional("{\"updatedAt\":\"2021-04-01T13:24:07.647Z\"}")
```
It says *data can not be read because its missing*.
I tracked it down to this location in ParseSwift code:
https://github.com/parse-community/Parse-Swift/blob/453ebdbcddf30cf3baad6bcf79fbc1fc0ba07fe2/Sources/ParseSwift/Authentication/Protocols/ParseAuthentication.swift#L429
The data object received from the server looks like this:
```
"{\"updatedAt\":\"2021-04-01T13:25:40.915Z\"}"
```
However ParseSwift expects this format:
```swift
internal struct UpdateSessionTokenResponse: Decodable {
var updatedAt: Date
let sessionToken: String
}
```
The sessionToken is missing.
This might be caused by using authentication wrong in my code. However I think a missing session token in the response should be handled explicitly by ParseSwift at this code location instead of just throwing an bad response format error.
What do you think?
When linking a user, a sessionToken
isn’t always provided.
Also, one of the developers found something related to preventLoginWithUnverifiedEmail
, in which, depending on what flags preventLoginWithUnverifiedEmail
changes, could be causing sessionToken
not to be sent:
opened 01:12AM - 08 Jan 22 UTC
closed 11:15PM - 24 Jan 22 UTC
type:bug
### New Issue Checklist
<!--
Check every following box [x] before submitti… ng your issue.
Click the "Preview" tab for better readability.
Thanks for contributing to Parse Platform!
-->
- [X] I am not disclosing a [vulnerability](https://github.com/parse-community/Parse-Swift/security/policy).
- [X] I am not just asking a [question](https://github.com/parse-community/.github/blob/main/SUPPORT.md).
- [X] I have searched through [existing issues](https://github.com/parse-community/Parse-Swift/issues?q=is%3Aissue).
- [X] I can reproduce the issue with the latest versions of [Parse Server](https://github.com/parse-community/parse-server/releases) and the [Parse Swift SDK](https://github.com/parse-community/Parse-Swift/releases).
### Issue Description
When sining up a User Parse sever response may not contain a sessionToken (Parse 4.2)
### Steps to reproduce
- Create a ParseUser subclass
```swift
import Foundation
import ParseSwift
struct User: ParseUser {
var emailVerified: Bool?
var password: String?
var authData: [String: [String: String]?]?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
public var objectId,
email,
qrCode: String?
}
```
- Uses one of the ParseUser methods to sign up an instance ()
```swift
var user = User();
user.password = password;
user.username = username;
user.email = email;
user.qrCode = "";
user.signup() { result in
switch result {
case .failure(let error):
//: Publish error.
self.error = error
print(error.message)
case .success(user):
print("Successfully queried data")
case .success(_):
print("Successfully queried data")
}
}
```
or
```swift
var user = User();
user.password = password;
user.username = username;
user.email = email;
user.qrCode = "";
let publisher = user
.signupPublisher()
.sink(
receiveCompletion: { result in
switch result {
case .failure(let error):
//: Publish error.
self.error = error
print(error.message)
case .finished:
print("Successfully queried data")
}
}, receiveValue: { user in
self.user = user
}
)
publisher.store(in: &subscriptions)
```
### Actual Outcome
Subscription results as an unknown error but the ParseUser is stored in database
### Expected Outcome
Returns a success or an explaination on why the outcome is an error
### Environment
Client
- Parse Swift SDK version: `3.0.0`
- Xcode version: `13.2.1`
- Operating system (iOS, macOS, watchOS, etc.): `iOS`
- Operating system version: ` 13-15`
Server
- Parse Server version: `4.2.0`
- Operating system: `N/A`
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): `Back4App`
Database
- System (MongoDB or Postgres): `MongoDB`
- Database version: `3.6`
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): `Back4App`
### Logs
```
(ParseSwift.ParseError) error = {
code = unknownError {}
message = "Invalid struct: No value associated with key CodingKeys(stringValue: \"sessionToken\", intValue: nil) (\"sessionToken\")."
otherCode = nil {
some = (_value = 0)
}
}
```
Also see:
opened 01:12AM - 08 Jan 22 UTC
closed 11:15PM - 24 Jan 22 UTC
type:bug
### New Issue Checklist
<!--
Check every following box [x] before submitti… ng your issue.
Click the "Preview" tab for better readability.
Thanks for contributing to Parse Platform!
-->
- [X] I am not disclosing a [vulnerability](https://github.com/parse-community/Parse-Swift/security/policy).
- [X] I am not just asking a [question](https://github.com/parse-community/.github/blob/main/SUPPORT.md).
- [X] I have searched through [existing issues](https://github.com/parse-community/Parse-Swift/issues?q=is%3Aissue).
- [X] I can reproduce the issue with the latest versions of [Parse Server](https://github.com/parse-community/parse-server/releases) and the [Parse Swift SDK](https://github.com/parse-community/Parse-Swift/releases).
### Issue Description
When sining up a User Parse sever response may not contain a sessionToken (Parse 4.2)
### Steps to reproduce
- Create a ParseUser subclass
```swift
import Foundation
import ParseSwift
struct User: ParseUser {
var emailVerified: Bool?
var password: String?
var authData: [String: [String: String]?]?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
public var objectId,
email,
qrCode: String?
}
```
- Uses one of the ParseUser methods to sign up an instance ()
```swift
var user = User();
user.password = password;
user.username = username;
user.email = email;
user.qrCode = "";
user.signup() { result in
switch result {
case .failure(let error):
//: Publish error.
self.error = error
print(error.message)
case .success(user):
print("Successfully queried data")
case .success(_):
print("Successfully queried data")
}
}
```
or
```swift
var user = User();
user.password = password;
user.username = username;
user.email = email;
user.qrCode = "";
let publisher = user
.signupPublisher()
.sink(
receiveCompletion: { result in
switch result {
case .failure(let error):
//: Publish error.
self.error = error
print(error.message)
case .finished:
print("Successfully queried data")
}
}, receiveValue: { user in
self.user = user
}
)
publisher.store(in: &subscriptions)
```
### Actual Outcome
Subscription results as an unknown error but the ParseUser is stored in database
### Expected Outcome
Returns a success or an explaination on why the outcome is an error
### Environment
Client
- Parse Swift SDK version: `3.0.0`
- Xcode version: `13.2.1`
- Operating system (iOS, macOS, watchOS, etc.): `iOS`
- Operating system version: ` 13-15`
Server
- Parse Server version: `4.2.0`
- Operating system: `N/A`
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): `Back4App`
Database
- System (MongoDB or Postgres): `MongoDB`
- Database version: `3.6`
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): `Back4App`
### Logs
```
(ParseSwift.ParseError) error = {
code = unknownError {}
message = "Invalid struct: No value associated with key CodingKeys(stringValue: \"sessionToken\", intValue: nil) (\"sessionToken\")."
otherCode = nil {
some = (_value = 0)
}
}
```
any update? I’m having this problem too.
user = await Parse.User.logInWith(platform + "_unionid", {
authData: {
id: unionid
}
}, {useMasterKey: true})
sessionToken = user.getSessionToken();
sessionToken is undefined
parse-server 6.4.0
when i set directAccess: false, it work nice. but i do not know why
1 Like
tayloruk:
directAccess
@Manuel @davimacedo also hitting this, i was logging in users from oauth2 using loginWith but with directAccess: true i can no longer return the session token back to the clientside for use with become(sessionToken)
As I understand it there is performance benefits to having directaccess true if server and client are not running on the same nodeJS process which they are not as they will be on different servers, is there some other way to achieve a sessiontoken in this kind of flow ?
Manuel
November 8, 2024, 12:15am
19
Note this open issue: Feature `directAccess` without tests · Issue #8808 · parse-community/parse-server · GitHub
Taking this out of the experimental state was maybe a bit hasty. I’m not surprised if we come across bugs in certain use cases with that option enabled.
Is there some solution i can implement now do you know ? or any clues what i can hack in to just get a session token back from loginWith