Allow all domains when adding a user to Azure B2C using the Graph API - microsoft-graph-api

I am trying to add a user with the email ...#gmail.com to my B2C directory via the Graph API (C#). I get this as a response:
The domain portion of the userPrincipalName property is invalid. You
must use one of the verified domain names in your organization.
This system needs to allow for users of any email domain to sign in. The users need to log in to a website, not have access to the Azure Portal.
Is there a way to accomplish this without manually adding every domain?
Code for adding user via Graph API:
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
var authProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphClient = new GraphServiceClient(authProvider);
var user = new User
{
AccountEnabled = true,
DisplayName = emailAddress,
MailNickname = emailAddress.Split('#').FirstOrDefault(),
UserPrincipalName = emailAddress,
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = true,
Password = tempPassword
}
};

If you're trying to create local B2C (not AAD) accounts try setting the identities property in your request but not the upn. This last should be auto-generated. Also password expirations must be disabled, and force change password at next sign-in must also be disabled.

I had to add following packages:
<PackageReference Include="Microsoft.Graph" Version="4.0.0-preview.7" />
<PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.7" />
Then:
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(Settings.ClientId)
.WithTenantId(Settings.Tenant)
.WithClientSecret(Settings.ClientSecret)
.Build();
var authProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphClient = new GraphServiceClient(authProvider);
var user = new User
{
AccountEnabled = true,
GivenName = "Name",
Surname = "Surname",
DisplayName = "Name Surname",
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = false,
Password = "pass.123",
},
PasswordPolicies = "DisablePasswordExpiration",
Identities = new List<ObjectIdentity>
{
new ObjectIdentity()
{
SignInType = "emailAddress",
Issuer = Settings.Tenant,
IssuerAssignedId = "sample#sample.com"
}
}
};
await graphClient.Users.Request().AddAsync(user);
Make sure to add permission to create users in Azure portal.

Related

How do I access Outlook365 mailbox using impersonation using .NET?

I'm using this code:
var cca = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
var ewsScopes = new [] { "https://outlook.office365.com/.default" };
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync(cancellationToken);
var service = new ExchangeService
{
Credentials = new OAuthCredentials(authResult.AccessToken),
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "mailbox#user.com"),
TraceListener = new TraceListener(),
TraceEnabled = true,
TraceFlags = TraceFlags.All
};
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
The code throws a ServiceRequestException (403) on the last line, and trace logs contains the error:
x-ms-diagnostics: 2000008;reason="The token contains not enough scope to make this call.";error_category="invalid_grant"
Do I need to expand the ewsScopes? Or is this because I'm lacking the correct permissions in Azure? Which roles/permissions do I need?
Check the token your using in
Credentials = new OAuthCredentials(authResult.AccessToken),
in jwt.io
What you should see in the roles is
If you don't have that role it means your application registration isn't correct (eg you have added the delegate permission instead of Application permission which is a common mistake).

(.Net 6) How to use OAuth 2 Azure AD to authenticate and Send email (With no prompt consent)

Guys I am trying to use a specific user to log in on Azure Add using Identity.Client and MailKit.
I am using this service in both projects (Web App and Console App).
It's prompted the consent all the time I need to remove the consent for the final user.
What can I do to get this working?
I have my application on Azure:
Authentication:
Certificates and secrets:
API permissions:
.Net 6 Code
private async Task<IPublicClientApplication> CreateClientApp()
{
var urlNoConsent = _config.GetSection("AzureAd:UrlNoConsent").Get<string>();
var options = new PublicClientApplicationOptions
{
ClientId = _config.GetSection("AzureAd:ClientId").Get<string>(),
TenantId = _config.GetSection("AzureAd:TenantId").Get<string>(),
RedirectUri = _config.GetSection("AzureAd:RedirectUri").Get<string>()
};
var app = PublicClientApplicationBuilder
.CreateWithApplicationOptions(options)
.Build();
_logger.LogInformation("Trying AcquireTokenByIntegratedWindowsAuth");
return app;
}
private async Task<AuthenticationResult> GetAzureAuthenticationToken(IPublicClientApplication app)
{
var tenantId = _config.GetSection("AzureAd:TenantId").Get<string>();
var scopes = _config.GetSection("AzureAd:Scopes").Get<string[]>();
var urlNoConsent = _config.GetSection("AzureAd:UrlNoConsent").Get<string>();
var prompt = Prompt.NoPrompt;
AuthenticationResult authToken = await app.AcquireTokenInteractive(scopes).WithPrompt(prompt).ExecuteAsync();
_logger.LogInformation("authResult.AccessToken = {0}", authToken.AccessToken);
return authToken;
}
public async Task<bool> SendEmail(string toEmail, string subject, string emailBody, bool ccAdmin = false)
{
var app = await this.CreateClientApp();
var authNewToken = await this.GetAzureAuthenticationToken(app);
var authToken = await this.RefreshAzureAuthenticationToken(authNewToken, app);
string senderEmail = _config["AzureAd:EmailFrom"];
using var client = new SMTPClient();
client.Connect("smtp.office365.com", 587, SecureSocketOptions.StartTls);
var oauth2 = new SaslMechanismOAuth2(authToken.Account.Username, authToken.AccessToken);
client.Authenticate(oauth2);
AlternateView avBody = await this.SetImagesLayout(emailBody);
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(senderEmail);
mailMessage.To.Add(toEmail);
mailMessage.Subject = subject;
mailMessage.AlternateViews.Add(avBody);
if (ccAdmin)
{
var users = await this.GetAdministrators("Administrator");
string[] emails = users.Select(x => x.Email).ToArray();
foreach (var email in emails)
{
mailMessage.CC.Add(new MailAddress(email)); //Adding CC email Id
}
}
//mailMessage.Bcc.Add(new MailAddress(bcc)); //Adding BCC email Id
var mime = (MimeMessage)mailMessage;
mime.WriteTo(#"c:\temp\mime-mm.eml");
client.Send(mime);
return true;
}
You can turn off the user consent like below.
Go to your application from the enterprise applications,
Then select option Do not allow user consent
But note that administrator must give admin consent
Then if the admin consent is given , the user wont get any consent screen after admin approval.
Edit:
From the enterprise applications select your application and see user consent tab in permissions tab Under security.
Remove the consent through powershell command below or through the graph api:
#Get that user or service principal using object Id
$ServicePrincipal = Get-AzureADServicePrincipal -ObjectId $AzureAdServicePrincipalObjectId
# Get list of all of the delegated permissions for that service principal
$spOAuth2PermissionsGrants = Get-AzureADOAuth2PermissionGrant -All $true| Where-Object { $_.clientId -eq $ServicePrincipal.ObjectId }
# To remove the consented permissions for that particular service principal
$spOAuth2PermissionsGrants | Where-Object PrincipalId -eq $UserPrincipalObjectId | Remove-AzureADOAuth2PermissionGrant
Reference : remove azureadoauth2permissiongrant | Microsoft Learn

The given token is invalid error in EWS OAuth authentication when using personal account

I have to get the contacts from Exchange server from any account, so we have used the code from below link.
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
But it is not working for personal accounts, which is working fine for our organization account. So I have used AadAuthorityAudience property instead of TenantId and changed the scope from EWS.AccessAsUser.All to others. Now authentication got success but getting "The given token is invalid" error while using the token in ExchangeService.
var pcaOptions = new PublicClientApplicationOptions {
ClientId = "77xxxxxxxxxxx92324",
//TenantId = "7887xxxxxxxxxxxxx14",
RedirectUri = "https://login.live.com/oauth20_desktop.srf",
AadAuthorityAudience = AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
//var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
var ewsScopes = new string[] { "User.Read", "Contacts.ReadWrite.Shared" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "araj#concord.net");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
What am doing wrong here?
https://outlook.office365.com/EWS.AccessAsUser.All is the right scope to use. The scope is invalid for personal accounts since they're not supported by EWS.

How to remotely access the Identity Manager API hosted on IdentityServer3?

I have searched and found something but without full documentation here.
Could someone please give me a step by step explanation?
I have IdentityServer3 well-configured and I confirm that I can access the IdentityManager through the browser and manage users perfectly. Now, I need to manage users but from another custom made application. So I need to:
Login through the custom app
Manage users through the Idm API.
I have used the "ResourceOwner" grant and used the "idmgr" scope to get an access token: https://localhost:44376/ids/connect/token.
But when I use that token to access https://localhost:44376/idm/api/users?count=10&start=0, I get the message "Authorization has been denied for this request."
var client = new HttpClient();
var dic = new Dictionary<string, string>();
dic.Add("client_id", "mvc");
dic.Add("client_secret", "secret");
dic.Add("grant_type", "password");
dic.Add("scope", "openid profile");
dic.Add("username", "yazan#catec.ae");
dic.Add("password", "P#ssword1");
var content = new FormUrlEncodedContent(dic);
var msg = client.PostAsync("https://localhost:44383/identity/connect/token", content).Result.Content.ReadAsStringAsync().Result;
string token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(msg).access_token;
var jwt = new JwtSecurityToken(token);
var identity = new ClaimsIdentity("ApplicationCookie", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
foreach (var c in jwt.Claims)
{
var t = c.Type;
var v = c.Value;
identity.AddClaim(new Claim(t, v));
}
IAuthenticationManager authenticationManager = HttpContext.GetOwinContext().Authentication;
authenticationManager.SignOut("ApplicationCookie");
authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, identity);
return Redirect("Index");

Google API Calender v3 Event Insert via Service Account using Asp.Net MVC

I have been trying to insert a Google calendar event via Google service account that was created for an app in my dev console, but I am continually getting a helpless 404 response back on the Execute method. In the overview of the dev console I can see that the app is getting requests because there are instances of errors on the calendar.events.insert method. There is no information on what is failing. I need this process to use the Service account process instead of OAuth2 so as to not require authentication each time a calendar event needs to be created.
I have set up the service account, given the app a name, have the p12 file referenced in the project. I've also, gone into a personal calendar and have shared with the service account email address. Also, beyond the scope of this ticket, I have created a secondary app, through an administration account and have granted domain wide access to the service account only to receive the same helpless 404 error that this is now giving.
Error Message: Google.Apis.Requests.RequestError
Not Found [404]
Errors [Message[Not Found] Location[ - ] Reason[notFound] Domain[global]
Any help identifying a disconnect or error would be greatly appreciated.
var URL = #"https://www.googleapis.com/calendar/v3/calendars/testcalendarID.com/events";
string serviceAccountEmail = "createdserviceaccountemailaq#developer.gserviceaccount.com";
var path = Path.Combine(HttpRuntime.AppDomainAppPath, "Files/myFile.p12");
var certificate = new X509Certificate2(path, "notasecret",
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { Google.Apis.Calendar.v3.CalendarService.Scope.Calendar },
}.FromCertificate(certificate));
BaseClientService.Initializer initializer = new
BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Test App"
};
Google.Apis.Calendar.v3.CalendarService calservice = new Google.Apis.Calendar.v3.CalendarService(initializer);
string timezone = System.TimeZone.CurrentTimeZone.StandardName;
var calendarEvent = new Event()
{
Reminders = new Event.RemindersData()
{
UseDefault = true
},
Summary = title,
Description = description,
Location = location,
Start = new EventDateTime()
{
//DateTimeRaw = "2014-12-24T10:00:00.000-07:00",
DateTime = startDateTime,
TimeZone = "America/Phoenix"
},
End = new EventDateTime()
{
//DateTimeRaw = "2014-12-24T11:00:00.000-08:00",
DateTime = endDateTime,
TimeZone = "America/Phoenix"
},
Attendees = new List<EventAttendee>()
{
new EventAttendee()
{
DisplayName = "Joe Shmo",
Email = "joeshmoemail#email.com",
Organizer = false,
Resource = false
}
}
};
var insertevent = calservice.Events.Insert(calendarEvent, URL);
var requestedInsert = insertevent.Execute();
I had the same problem. The solution was to add an email client, whose calendar event you want to send.
Credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = Scopes,
User = "example_client_email#gmail.com"
}.FromCertificate(certificate));
So I found out that for this to work, You need to make sure that you access the google.Admin account for referencing the service account Client ID of the app you created.
Another thing that helps is making sure the timezone is in the following format "America/Phoenix"
I have now successfully created events through the service account WITHOUT authentication.

Resources