we are using both windows authentication and forms based authentication in a claims aware SharePoint WebApplication. The custom MembershipProvider (datasource: Novell eDirectory) works just fine but I'm uncertain about a few things.
The cn property of each user record is a unique identifier (hexadecimal value).
Users are logging in using their email addresses (and password) though. We don't want to make the unique identifier visible anywhere.
GetUser(string username, bool userIsOnline)
FindUsersByEmail(...) and
FindUsersByName(...)
return MembershipUser(s) which are constructed this way:
CustomMembershipUser membershipUser = new CustomMembershipUser(
providerName: Name, // the membership provider's name
userName: providerUserKey, *// the "cn" name*
providerUserKey: providerUserKey, *// again the "cn" name*
email: email, // the email used to log in
passwordQuestion: null,
comment: null,
isApproved: true,
isLockedOut: false,
creationDate: DateTime.MinValue,
lastLoginDate: DateTime.MinValue,
lastActivityDate: DateTime.MinValue,
lastPasswordChangedDate: DateTime.MinValue,
lastLockedOutDate: DateTime.MinValue,
firstName: givenName,
lastName: surName);
The last two parameters are "Custom-"MembershipUser parameters. My ultimate goal is to display users in an Windows-Integrated-Authentication-style "LastName, FirstName".
Right now upon entering my email address the people picker resolves my email address to a "cn" name which is something like XYZ12345. Instead I want to display "LastName, FirstName" throughout SharePoint. The information is present in the datasource (eDirectory) and I can enrich my CustomMembershipUser with this information but of course neither the PeoplePicker nor anything else in SharePoint will be aware of my custom MembershipUser.
Is there anything claims related I should be aware of?
Related
I'm trying to create an envelope. My flow is next:
Obtaining OAuth token
Creating envelope based on existing template
Using createRecipientView method to get redirect url for the first signer(Later I'm taking the existing envelope id and creating redirect url for the second signer)
The problem:
It works as I expect if only signer's email address belongs to my docusign developer account. In other words if it is in the list of my docusign dev account users. Otherwise, with any random email address, I'm being redirected to the document page but I'm only able to view it and close, there's no start->sign->finish button(I'm not able to sign a doc).
One thing I've noticed is the wrong recipientId which is equal to zeros and dashes(normally it has a set of numbers and letters). I find it at a signing page -> other actions -> Session Information. It's hapenning when I'm being redirected as a user with any email(one that does not belong to docusign account). BUT, every signer receives an email notification with the same link to the document and If I go from that link, I can sign a document no matter what email address it is.
Session information with the wrong recipientId
My code:
const client = new docusign.ApiClient()
client.setBasePath('https://demo.docusign.net/restapi')
client.setOAuthBasePath('account-d.docusign.com')
const tokenResponse = await client.requestJWTUserToken(userId, integrationKey, ['impersonation', 'signature'], privateKey, 600)
client.addDefaultHeader('Authorization', `Bearer ` + tokenResponse.body.access_token)
const envelopesApi = await new docusign.EnvelopesApi(client)
const envelope = await envelopesApi.createEnvelope(accountId, {
envelopeDefinition: {
templateId: templateId,
status: 'sent',
emailSubject: `Signing template ID: ${templateId}`,
templateRoles: [
{ roleName: args.firstRole, name: args.firstSignerName, email: args.firstSignerEmail },
{ roleName: args.secondRole, name: args.secondSignerName, email: args.secondSignerEmail },
],
}
})
const recipientView = await envelopesApi.createRecipientView(accountId, envelope.envelopeId, {
recipientViewRequest: {
returnUrl: my local host,
email: args.firstSignerEmail,
userName: args.firstSignerName,
authenticationMethod: 'none',
},
})
return recipientView
Please, let me know If you know what I'm doing wrong.
I read docusign docs and thought I'm missing some permission, but so far can't figure out what's the problem
I could be wrong but based on your description, you haven't set up a clientUserId parameter for your recipients. Recipient Views are created for embedded signers wherein you embed the signing session into your own application. As embedded recipients are a special class of recipients associated only with the sender's account, this could explain why your recipient view works for users already part of your account but does not work for anyone else.
Here is how my application works. A user logs in for the first time using Google Sign in. We get the following data from their Google Account:
Given name
Family name
Email ID
We wish to use this information to call our API (POST request) to create a user profile.
The data we send is
{
firstName: firstName ,
lastName: lastName,
email: email
}
Here is where the issue comes from. The user profile has many fields and one of them is designation. When the user logs in for the first time, we don't know their designation.
We are using MongoDB for our database. So we use Mongoose to set up the connection. In Mongoose model, we have added some validation for our schema. Designation is a required field. It should be at least one character of length and maximum of 40 characters. If we set designation as null, the validation would fail.
Is there any way to allow null in a required field in Mongoose?
Rather than setting required to true or false, you can pass it a function:
const user = new Schema({
designation: {
type: String,
minLength: 1,
maxLength: 40,
required: function() {
// Rather than checking a stored variable, you could check
// static functions on the model, a custom value on the
// instance that isn't persisted, etc.
return this.hasLoggedInAtLeastOnce === true;
// If this function returns true, the field is required.
}
}
hasLoggedInAtLeastOnce: {
type: Boolean,
}
});
I have a user in database with following credentials:
{
"_id": "zTHv8yqPSm3pmi4So",
"emails": [{"address": "someemail#example.com", "verified": true}],
"services" : {
"password" : {
"bcrypt" : "$2b$10$L6HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo1IjZEx6.PBxfOeQHqS."
},
"resume" : {
"loginTokens" : [ ]
}
},
"username": "some#username",
"profile": {
"firstName": "Example",
"lastName": "User",
}
}
When I try to login user with username it says user not found:
Meteor.loginWithPassword("some#username", "123456", function(error) {
console.log(error.reason);
});
It works fine for email but not for username.
I want flexibility to login user with either of email or username
The API Meteor.loginWithPassword actually takes a "selector" as first argument:
https://docs.meteor.com/api/accounts.html#Meteor-loginWithPassword
Meteor.loginWithPassword(selector, password, [callback])
ARGUMENTS
selector Object or String
Either a string interpreted as a username or an email; or an object with a single key: email, username or id.
In your case you use the string form, and let Meteor try to guess whether it is a username or an email.
But since your username contains an "#" character, this misleads Meteor into interpreting it as an email:
https://github.com/meteor/meteor/blob/release/METEOR%401.12.1/packages/accounts-password/password_client.js#L33-L38
Meteor.loginWithPassword = (selector, password, callback) => {
if (typeof selector === 'string')
if (!selector.includes('#'))
selector = {username: selector};
else
selector = {email: selector};
That is why when you try with the email it works fine, but fails for the username containg the "#".
And the simple solution is to explicitly tell Meteor that you target the username (and not an email, despite the "#"):
Meteor.loginWithPassword({
username: "some#username"
},
"123456",
function(error) {
console.log(error.reason);
}
);
Now, if I am trying to guess further your objective, you want your user to be able to provide either their email or username as login identifier, without explicitly telling which it is? (Like a kind of "omni" login id input)
In that case, unfortunately you will have to detect yourself whether it is an email or username. If the latter really follows a pattern like "some#username", you can try to detect that the domain is incomplete (no extension).
But if any of your user did register a username which really looks like an email (e.g. "some#user.name"), then you may not be able to differentiate them.
Even worse, some user may choose a username that is exactly the email address of another user! In that case, how to tell which one is trying to log in?
IMHO, this then becomes much trouble for marginally improved UX. Either prevent usernames containing "#", i.e. enforce a rule that enables you telling the difference, or provide a way for the user to explicitly tell if it is an email or username when it is ambiguous (e.g. it can be some radios to tell which type it is; it can still contain an "auto" mode for when the login id is unambiguous).
BTW we could also imagine performing a 2 steps login attempt: first as is, then if username contains an "#", explicitly as a username as described above. But we may still fall into the above described worst case scenario...
I'm creating new user using GraphServiceClient with SignInType as userName something like this:
var user = new User
{
AccountEnabled = true,
GivenName = "Joe",
Surname = "Bob",
DisplayName = "Name",
Mail = "joe#bob.com",
MobilePhone = "111111111",
Identities = new List<ObjectIdentity>()
{
new ObjectIdentity
{
SignInType = "userName",
Issuer = "<Issuer...>",
IssuerAssignedId = "someName"
},
},
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = false,
Password = "<pass>"
},
PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword",
};
await gsc.Users.Request().AddAsync(user);
After that user is created in Azure and I can use this account for login into app that is using B2C SignIn policy. But when I want invoke ResetPassword policy for that user, after successfully email verification, I'm getting error: "An account could not be found for the provided user ID.". After some trial and error I've figure out that there is missing data in azure user profile tab "Authentication methods" When I fill out input for email everything is working fine and user is able to reset password.
So I'm searching for a way how to populate user email into this section "Authentication methods" during creation time.
In this circumstance, where you want to create users via Graph API, you cannot populate the strongAuthenticationEmail attribute usng Graph API. This attribute holds the email associated with a username based account for password reset operations. User Flows will read this attribute during password reset. Therefore this wont work.
You need to use a custom policy for a username based journey and replace all instances of strongAuthenticationEmail with extension_whatever. Then in your Graph API payload, insert the email address in a key called extension_GUID_whatever.
https://github.com/azure-ad-b2c/samples/tree/master/policies/username-signup-or-signin
I've a Nodejs app and I use Passeport to let my users connect throught Facebook or Google via Oauth. I'm storing basic data after connection such as : uid, firstname etc.
How can I be assured that the uid I'm receiving will be always unique for a given user ? I mean, data is coming either from Facebook or Google, so why couldn't I face a nasty duplicate uid for different users someday ?
The id you are getting via OAuth is unique when you are using either Facebook or Google. But if you want to use both then I would suggest make your dbSchema (if you are using mongoose) like this -
var userSchema = new mongoose.Schema({
local: {
username: String,
password: String
},
facebook: {
id: String,
token: String,
email: String,
name: String
},
google: {
id: String,
token: String,
email: String,
name: String
}
});
The UID is unique only within the scope of that single provider’s list of users.
This article suggests you combine the provider’s name plus the UID to get a unique value.
Combination of provider’s name and uID will uniquely identify user inside our app.
I would use the provider’s domain name such as “google.com” or “com.google”.