Authorization in mongodb - c#

The readonly users have only read permissions. Thus, a user having readonly true is not authorized to add new user or any write capabilities.
I am building a utility which manages the data in MongoDB. When i log in as readonly user it should not allow me to add new user. When I implement it, it does not actually add a user but it is not throwing any exception.
Here is my commands for adding a readonly user
var credentials = new MongoCredentials(username, password,false);
var addUser = new MongoUser(credentials, readOnly);
var database = server.GetDatabase(databaseName);
database.AddUser(addUser);

Did you start mongod with the --auth command line argument?
Did you use safe=true on your connection string?
Also, you need to use admin credentials to add a user to a database:
var adminCredentials = new MongoCredentials("adminuser", "adminpassword", true);
var userCredentials = new MongoCredentials("username", "password");
var user = new MongoUser(userCredentials, true);
var fooDatabase = server.GetDatabase("foo", adminCredentials);
fooDatabase.AddUser(user);
Notice that there are two sets of credentials: one for the user being added, and another set of admin credentials for your code to be able to add the user.

Related

Get user data from a TokenCredential object (.NET)

I'm building a .NET core tool (Console app) that needs to access some Azure Keyvault secrets by using a SecretClient. This client needs a TokenCredential for which I use DefaultAzureCredential().
The client is successfully authenticated and retrieves the secrets, but can I know which method from the flow was used (i.e. Environment, Cache, CLI, interactive)? I want to display the username that was used for logged in, since you might have an account in SharedCache but you might want to use another account.
var credentials = new DefaultAzureCredential();
var secretClient = new SecretClient(new Uri(configuration["Authentication:KeyVaultUri"]), credentials);
// Just using the client to retrieve values
var settings = JsonSerializer.Deserialize<AppSettingsKeys>((await secretClient.GetSecretAsync(configuration["Authentication:SecretName"])).Value.Value);
I checked the credential object but didn't see anything useful to get the username. I want to Console.WriteLine something like Successfully logged in with pepe#test.com using SharedTokenCacheCredential
I was able to get the upn by first getting the jwt with the GetToken method, and then parsing it with a JwtSecurityTokenHandler.
Not the approach I was looking for but it works, I was wondering if there is cleaner way.
var credential = new DefaultAzureCredential();
var secretClient = new SecretClient(new Uri(configuration["Authentication:KeyVaultUri"]), credential);
var settings = JsonSerializer.Deserialize<AppSettingsKeys>((await secretClient.GetSecretAsync(configuration["Authentication:SecretName"])).Value.Value);
var token = await credential.GetTokenAsync(
new Azure.Core.TokenRequestContext(
new[] { "https://vault.azure.net/.default" }));
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(token.Token) as JwtSecurityToken;
var upn = jsonToken.Claims.First(c => c.Type=="upn").Value;

Microsoft Graph API - user extension data in C#

I have an Azure AD B2C directory with some users in it. I have been using the Microsoft Graph API and through both https://developer.microsoft.com/en-us/graph/graph-explorer and PostMan I have been able to create and modify users along with including an extension attribute (eg: extension_[guid in our tenant]_ContactMethod) - details passed in json in the body of the request in PostMan.
That is fine, however I need to be albe to do the same in C#. I can successfully create the user without specifying any extensions:
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var user = new User
{
AccountEnabled = true,
DisplayName = "John Smith",
MailNickname = "JohnSimth",
UserPrincipalName = "JohnSmith#[tenant].onmicrosoft.com",
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = true,
Password = "[Randomly Generated Password]"
}
//[Extension attributes to add here]
};
await graphClient.Users.Request().AddAsync(user);
However I need to be able to specify some extension attributes when creating / modifying the user in C#. How do I do this?
You cannot directly add extensions at the time of creation according to this limitations document.
After creating the user, you need to create a separate request that hits the extensions endpoint as shown in the below code and this adds these extension details to the user.
var extension = new OpenTypeExtension
{
ExtensionName = "{ExtensionName}",
AdditionalData = new Dictionary<string, object>
{
{"FirstEmail", "abc#yahoo.com"},
{"SecondEmail" , "xyz#yahoo.com"}
}
};
await graphClient.Users["{UserId}"].Extensions
.Request()
.AddAsync(extension);
So just after user creation, get that userid and use it to hit extensions endpoint as shown in the above code.

Migrating plain-text password to asp.net Identity 2.1

I am moving an existing site to mvc and one of the thing that puzzles me is the migration of user data, particularly passwords, these passwords are stored as plain text (yes i know). Now moving the rest of the account information to aspnet identity tables is easy but I need to now hash these passwords and I am not sure how to properly hash them before storage (using tsql), if i must use a .net app to hash, what class do i need to call by feeding it plain password and it will give me a hash?
thank you
It seems like your application isn't set up right for a complete migration, so I have an idea for an easy solution to get the full use out of the Identity 2.0 database and features.
Create New Web Application, then create a method that gets the plain text login credientials for your old users. Next:
When you create a new application look at the code in the account/register files.
Here is what you see:
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signInManager = Context.GetOwinContext().Get<ApplicationSignInManager>();
var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text };
IdentityResult result = manager.Create(user, Password.Text);
if (result.Succeeded)
{
}
Now create a class to hold all the properties from your existing user, or you could use a SQLDataReader["columnName"] if you wanted to go the rout of looping a reader.
So copy that code run your new Method:
var ListOfUsers = MyMethodThatRetunsAllOldMembers();
foreach member in ListOfUsers{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signInManager = Context.GetOwinContext().Get<ApplicationSignInManager>();
var user = new ApplicationUser() { UserName = Member.UserName, Email = Member.Email };
IdentityResult result = manager.Create(member.LoginName, Member.Password);
//Example: You can even add roles at the same time.
var ra = new RoleActions();
ra.AddUserToRoll(member.LoginName, Member.Email, userRole);
}
This will create the new hashed passwords as well as settings roles and userid's for each of your old users, effectively migrating your database.

Why does open OpenLDAP require a cn=username?

I'm connecting to OpenLDAP with C#, and when I pass in my username and password, I have to pass them into my LdapConnection object as cn=Username, Password. If I just pass in username and password my call to Bind fails. Why do I have to do that? Is something misconfigured on my OpenLDAP server?
It's just a byproduct of the implementation. Novell's eDirectory solution takes a very similar approach, and I use the same Novell.Directory.Ldap code to handle bind requests to both eDirectory and OpenLDAP. Now obviously, the users themselves shouldn't have to enter their entire CN when authorizing - we can just issue a search for them, based of thier UID :
//Setup the initial bind for the admin user
var lc = new LdapConnection();
lc.SecureSocketLayer = SSL;
lc.UserDefinedServerCertValidationDelegate += delegate { return true; };
lc.Connect(ServerName, Port);
lc.Constraints.TimeLimit = Timeout;
lc.Bind(AdminUsername, AdminPassword);
Now I just filter for the user, and bind using their distinguished name, or full container name (CN) :
//Ex. (uid=jsmith)
string filter = config.LdapAuth.LdapFilter.Replace("{{uid}}", username);
//Find the user we're trying to authorize
var lsc = lc.Search(config.LdapAuth.LdapDomain, LdapConnection.SCOPE_SUB, filter, null, false);
if (lsc.hasMore())
{
LdapEntry nextEntry = lsc.next();
//Check the Entries DN so we can properly bind
lc.Bind(nextEntry.DN, Password);
}
This was the most widely used approach I could find, and it's worked quite well so far.

Authorizing with stored credentials. Google Drive API for .NET

I'm trying to create desktop application which will allow to list files and folders on google drive account. On this momment I'm able to do it but there is a one issue. I have to re-login each time I want to open google drive account from my application. Is it possible to use stored locally AccessToken/Refresh tokens in order to avoid re-authorization each time?
Here method which is used to get authorization.
private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
IAuthorizationState state = new AuthorizationState(new[] { "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" });
// Get the auth URL:
state.Callback = new Uri("urn:ietf:wg:oauth:2.0:oob");
UriBuilder builder = new UriBuilder(arg.RequestUserAuthorization(state));
NameValueCollection queryParameters = HttpUtility.ParseQueryString(builder.Query);
queryParameters.Set("access_type", "offline");
queryParameters.Set("approval_prompt", "force");
queryParameters.Set("user_id", email);
builder.Query = queryParameters.ToString();
//Dialog window wich returns authcode
GoogleWebBrowserAuthenticator a = new GooogleWebBrowserAuthenticator(builder.Uri.ToString());
a.ShowDialog();
//Request authorization from the user (by opening a browser window):
string authCode = a.authCode;
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
SOLVED:
In order to invoke methods from Google Drive sdk first you need to instance of service:
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description, GoogleDriveHelper.CLIENT_ID, GoogleDriveHelper.CLIENT_SECRET);
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
Service = new DriveService(auth);
Those CLIENT_ID and CLIENT_SECRET you will have after you sign up for application in Google API console.
Then you need to define GetAuthorization routine, which might look as following:
private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
IAuthorizationState state = new AuthorizationState(new[] { "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" });
state.Callback = new Uri("urn:ietf:wg:oauth:2.0:oob");
state.RefreshToken = AccountInfo.RefreshToken;
state.AccessToken = AccountInfo.AccessToken;
arg.RefreshToken(state);
return state;
}
It will works if you already have Refresh and Access tokens (at least Refresh). So you need to authorize for some user account first.
Then you can use that Service instance to invoke sdk methods.
Hope it will help someone.

Categories

Resources