I have attempted this with not much success. Basically I need to login to Exchange using EWS remotely.
The issue is I don't know if the user has logged in OK or if the credentials are wrong as I get nothing back! If I provide wrong credentials the software just carries on!
Is there something I'm missing, I've checked the MSDN stuff about EWS which shows you how to connect to exchange but nothing about validating credentials!
Below is the code I currently have to connect.
public void connect(string Email, string Password)
{
try
{
_useremail = Email;
_userpass = Password;
// Define the credentials to use.
var credentials = new WebCredentials(_useremail, _userpass);
_ExchangeServer = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
_ExchangeServer.Credentials = credentials;
_ExchangeServer.Url = new Uri(_ExchangeEWSURL);
_ExchangeServer.Timeout = 60;
_ExchangeServer.KeepAlive = true;
_ExchangeConnected = true;
}
catch (Exception ex)
{
_ExchangeConnected = false;
throw ex;
}
}
as you can see at present I just set a bool value to true in the class. Any ideas?
In order to check whether the given credentials are valid, you must query resources you expect the user to have access to (calendar, inbox, contacts, etc.). There is no explicit login method - the authentication occurs implicitly when you request user resources (via FindItems, FindFolders, FindAppointments, etc.).
Related
We are using below code to authenticate user credentials,
string domainAndUsername = this.activeDirectoryConfiguration.Domain + #"\" + username;
DirectoryEntry entry = null;
try
{
entry = new DirectoryEntry(
this.activeDirectoryConfiguration.LdapPath,
domainAndUsername,
password);
// Bind to the native AdsObject to force authentication.
object nativeObject = entry.NativeObject;
if (nativeObject == null)
{
return AuthenticationDetails.InvalidCredentials;
}
}
catch (DirectoryServicesCOMException directoryServicesComException)
{
return this.CheckErrorResponse(username, directoryServicesComException);
}
finally
{
if (entry != null)
{
entry.Dispose();
}
}
This code works fine when using NTLM authentication. Here we are checking error code we get from the 'DirectoryServicesCOMException' to identify whether account is locked or disabled or if the password is expired.
In our production environment, kerberos authentication is used where this code is failing. It throws System.Runtime.InteropServices.COMException which doesn't have detailed description about the failure. Every time it just throws
Message=Logon failure: unknown user name or bad password.
Can anyone suggest why isn't Kerberos giving detailed exception or is there any way to identify various login failures while using kerberos?
So I wanted the users to login to my app using Microsoft Account
I did all the setup in my mobile service in Azure and this is how I implement the login in my App:
private async Task<bool> AuthenticateAsync()
{
string message;
bool success = false;
try
{
user = await App.MobileService
.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
message =
string.Format("You are now signed in - {0}", user.UserId);
success = true;
}
catch (InvalidOperationException)
{
message = "You must log in. Login Required";
}
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
return success;
}
all is working fine but all I get from this is a User Id.
and I need the name of the user that logged in, can anyone help me how should I go about this?
Thanks
and I need the name of the user that logged in, can anyone help me how should I go about this
For UWP app, this is impossible using official managed API. See MobileServiceAuthentication class in here
internal async Task<MobileServiceUser> LoginAsync()
{
string response = await this.LoginAsyncOverride();
if (!string.IsNullOrEmpty(response))
{
JToken authToken = JToken.Parse(response);
// Get the Mobile Services auth token and user data
this.Client.CurrentUser = new MobileServiceUser((string)authToken["user"]["userId"]);
this.Client.CurrentUser.MobileServiceAuthenticationToken = (string)authToken[LoginAsyncAuthenticationTokenKey];
}
return this.Client.CurrentUser;
}
The official sdk just retrieves the userId and MobileServiceAuthenticationToken, for other platform, we need to use GetIdentitiesAsync() method to get identity, see How to get user name, email, etc. from MobileServiceUser? or LINK
The username info actually has been retrieved in the SSO process:
So you have to implement the auth process(Extend the method based on the open source code) and maintain the username information as you need.
If you can get the user's input, maybe you can also call Live API: https://msdn.microsoft.com/en-us/library/office/dn659736.aspx#Requesting_info
Using Exchange EWS managed API 2.0, here is a method which I'm using to validate credentials:
public static bool TestExchangeConnetion(UserSettingDTO credential, ServerSettingDTO serverSetting)
{
bool authenticated = false;
Microsoft.Exchange.WebServices.Data.ExchangeService service;
service = new ExchangeService((ExchangeVersion)Enum.Parse(typeof(ExchangeVersion), serverSetting.ExchangeVer));
service.Url = new Uri(serverSetting.ExchangeURL);
service.Credentials = new NetworkCredential(credential.ExchangeUsername, credential.ExchangePassword);
try
{
//make a call to ensure that credentials are working
AlternateIdBase response = service.ConvertId(new AlternateId(IdFormat.EwsId, "Placeholder", credential.ExchangeUsername), IdFormat.EwsId);
}
// The credentials were authenticated. We expect this exception since we are providing intentional bad data for ConvertId
catch (ServiceResponseException)
{
authenticated = true;
}
// The credentials were not authenticated.
catch (ServiceRequestException)
{
authenticated = false;
}
catch (Exception)
{
authenticated = false;
}
return authenticated;
}
This works absolutely fine to validate credentials but I'm looking for a way to differentiate between invalid credentials and Exchange server downtimes. This code returns false for both.
Is it possible to find out if there is an issue communicating to the server (like server downtimes)? The reason for this is I want to notify the user about invalid credentials not server downtimes!
EWS is just a Web-service that runs on IIS (so IIS is looking after authentication) if you just want to check the credentials why don't you just make a Get request against the services.wsdl file or a Get on the Autodiscover endpoint on the CAS server. If the credentails are incorrect that should return a 401 at that point.
Cheers
Glen
Every time I try to call the server, I get an error code : ErrorConnectionFailed with Connection failed. Try later. message.
I suspect that it comes from the fact that the credentials of service are empty. Although I have no idea why. If I create the credentials manually using my windows account login and password, it works fine : new WebCredentials(login, password, domain);
I have a console program that works fine (see below), but it does not on a web site.
static void Main(string[] args)
{
var service = GetContextualService(email);
EmailMessage email = EmailMessage.Bind(service, new ItemId(validEmailId));
Console.ReadKey();
}
private static ExchangeService GetContextualService(string email)
{
ExchangeService service = new ExchangeService();
// I don't even need credentials on a Console program to make it work
//service.Credentials = new WebCredentials(CredentialCache.DefaultCredentials);
//service.UseDefaultCredentials = true;
service.AutodiscoverUrl(email, RedirectionUrlValidationCallback);
return service;
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
While using on a website even with new WebCredentials(CredentialCache.DefaultCredentials);, it returns an exception. (see below)
private ExchangeService GetContextualService(string email)
{
ExchangeService service = new ExchangeService();
service.Credentials = new WebCredentials(CredentialCache.DefaultCredentials);
//service.UseDefaultCredentials = true;
service.AutodiscoverUrl(email, RedirectionUrlValidationCallback);
return service;
}
[HttpPost]
public List<InternetMessageHeader> GetMailHeader(JObject data)
{
ExchangeService service = GetContextualService(data.GetValue("email").Value<string>());
ItemId id = new ItemId(data.GetValue("mailId").Value<string>());
// EXCEPTION BELOW
EmailMessage email = EmailMessage.Bind(service, id);
return email.InternetMessageHeaders.ToList();
}
Why does any call to EWS returns me an exception ?
Why is it working fine on a console program and not on a web server ?
Any thought is welcome !
Strictly based on the code you posted, all I can say is that when you call AutoDiscoverUrl() it may not be talking to the same server that you need to talk to with EWS. Altho typically AD and EWS are on the CAS, it's possible (I think) to get an EWS URL that points to some other server. I've not been in the code in the EWS Editor in some time, but if it does not call the Managed API, it might do AD slightly differently. I'd suggest calling out the EWS URL before you try the Bind() and seeing if you can paste it into a browser. (It'll redirect you OWA, but the connection will be proven.) I'd also call out the AD URL in the redirection callback so you know who you're talking to. Sorry I can't be of more help.
I need to connect to an external LDAP server that is accessible to me but only over LDAPS.
The information I have available is username, server, password. I need to query and retrieve a list of all users. The format I have the details in are
Username: domain\username
Password: {password}
Domain: remote.{domain}.net.au
The following code I wrote will authenticate my user account successfully, but I now need to enumerate all users which is where I'm having issues. Ideally this would be ALL users in the directory, not from within a specific OU. Again, I don't have the fully qualified paths to any OUs for this server. The server has a self signed certificate which is why in my example I am specifically telling it to accept the certificate.
int port = secured ? 636 : 389;
LdapConnection connection = new LdapConnection(new LdapDirectoryIdentifier(ldapServer, port, false, false));
if (secured)
{
connection.SessionOptions.ProtocolVersion = 3;
connection.SessionOptions.SecureSocketLayer = true;
}
connection.Credential = new NetworkCredential(username, password);
connection.AuthType = AuthType.Basic;
connection.SessionOptions.VerifyServerCertificate += (conn, cert) => { return true; };
connection.Bind();
return connection;
So the answer is in Performing a Simple Search sample of Introduction to System.DirectoryServices.Protocols (S.DS.P) with :
// create a search filter to find all objects
string ldapSearchFilter = "(&(objectCategory=person)(objectClass=user))";