LDAP Authentication Fails in Azure App Service - azure

I have created a Java web app and deployed it on Azure App Service. In the app, we are providing users with a Login Page and upon submitting the credentials the users are authenticated using LDAP. This is working when deployed locally.
When I deploy this to Azure as WebApp, the authentication doesn't happen and the application gives an error. I am trying to authenticate like below. The LDAPContext is always returned as null in Azure.
The Authentication/Authorization settings in Azure Portal is turned OFF.
LdapContext ctx = null;
String dn= "uid=" + username + ",ou=users,ou=xxxx,o=xxxxx";
String ldapURL = "ldap://ldap.example.com:389";
Hashtable<String, String> environment =new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapURL);
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, dn);
environment.put(Context.SECURITY_CREDENTIALS, password);
ctx = new InitialLdapContext(environment,null);

Server Side: Check the inbound Security rule for Which Ip address are can access the LDAP
If you pass the LDAP domain name in code . Try pass empty value that place
Try to give Auth type is Basic or Negotiate or Anonymous etc . these are in .Net Frame work same way try some other type in Java may be . So try like that
ldap://ldap.example.com - For this example.com is domain name

Related

Azure Application Gateway support Open ID connect Authentication

I have an azure web app , which has open id connect authentication configured with Azure AD
For this , i had created a new app under App Registrations in Azure Active Directory and configured the Redirect URL as /signin-oidc . So when i try to login to the app service url , it first redirects to the redirect url and then to https://login.microsoftonline.com and passes the client id ,tenant etc details in the query string and works perfectly fine. So i can login with my azure ad user credentials
The Web Application is working perfectly fine with Open ID Connect with Azure AD.
When i front Azure Web App , with an Azure Application Gateway , it directly redirects to
/signin-oidc and stops there . I tried redirect options also.
Does Azure Application Gateway support -open id connect authentication with Azure AD. ?
Same scenario here, an App Service behind an Application Gateway. Here's what worked:
The BuildRedirectUri method in Microsoft.AspNetCore.Authentication.AuthenticationHandler<> builds the redirect URI concatenating, among other values, the Resquest.Host string. That's why the App Service host was being used instead of the Gateway's.
So, the following code snipped was added to the Configure() method of Startup.cs:
if (env.IsProduction())
{
app.Use((context, next) =>
{
context.Request.Host = new HostString("<gateway.host>");
return next();
});
}
Yes , we can use application gateway with open id authentication. In my case, SSL certificate was missing and i got it working once added.

How can I allow a service account to access my REST API when using Roles-based Authorization in Azure?

Summary: I have a REST API that I use for functional testing. I only allow people or groups in a specific "Tester" role to hit the API. I want to trigger this functional testing during an Azure DevOps Release Pipeline automatically, but I can't figure out how to authorize the machine account to hit the API.
Details:
I have this API secured with [Authorize(Roles = "Tester")]
[Route("quotas/developers")]
[HttpGet]
[Authorize(Roles = "Tester")]
[SwaggerResponse(HttpStatusCode.OK, "Successful operation", Type = typeof(DeveloperQuota[]))]
public async Task<List<DeveloperQuota>> GetDeveloperQuota([FromUri]string developerUpn)
To set this up, I have an Enterprise Application registered in Azure Active Directory. In the manifest, I declare the role.
And then in the Enterprise Application I add some users and groups which are assigned the role "Tester."
This works fine for running my functional tests by hand. I run the tests, it pops up an oauth dialog for me to enter my credentials, it grabs my Bearer token from the successful auth request then passes it along to the APIs.
private string GetActiveDirectoryToken()
{
string authority = this.configuration.ActiveDirectoryAuthority;
string resource = this.configuration.ActiveDirectoryAudience;
string keyVaultUri = this.configuration.KeyVaultUri;
IKeyVaultAdapterFactory keyVaultAdapterFactory = new KeyVaultAdapterFactory();
var keyVaultAdapter = keyVaultAdapterFactory.CreateInstance(KeyVaultServicePrincipal.PowerShellAppId);
SecureString clientIdSecure = keyVaultAdapter.GetAzureKeyVaultSecretSecure(keyVaultUri, "GasCallbackRegistrationClientID", null).Result;
SecureString redirectUriSecure = keyVaultAdapter.GetAzureKeyVaultSecretSecure(keyVaultUri, "GasCallbackRegistrationClientIDRedirectUri", null).Result;
var authContext = new AuthenticationContext(authority);
var result = authContext.AcquireTokenAsync(
resource,
SecureStringUtilities.DecryptSecureString(clientIdSecure),
new Uri(SecureStringUtilities.DecryptSecureString(redirectUriSecure)),
new PlatformParameters(PromptBehavior.Auto)).Result;
return result.AccessToken;
}
Of course, if I'm running this during automation, there will be nothing to fill in the dialog with creds, nor do I want to be storing a copy of these creds, especially since these creds roll on a schedule which are maintained elsewhere.
My thought was that I could create an Azure Service Principal, associate a cert with the service principal, install the cert on my deployment machine, login as the Service Principal if the cert was available, and then put that Service Principal in the "Tester" role. The problem is I can't add a Service Principal as a user in the Enterprise Application. It only appears to allow me to add "Users and groups." I similarly can't add a service principal to a group.
Any thoughts on how I can authorize my deployment box to hit these APIs?
Roles published for applications are treated as application permissions and not assignable to other apps via the "Users and Groups" assignment screen.
To assign the app permissions to a client app, go to the client app's registration page, click on Api Permissions and then Add a Permission. Select the My Api tab, search for your application that published the app roles and you'd see the app role listed in the list below. Select that, save and then grant admin consent.

Azure MSI using app services

I am trying to protect my backing services to my frontend webapp using MSI and AAD auth.
I keep getting a 401 when I call my backing services form the public facing webapp. I have added the public webapp as a reader in the IAM section of the backing services.
What I can't figure out is how to obtain the access token, it seems that no matter which endpoint I use for obtaining the access token, it says that it is not found.
Here is my code:
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = azureServiceTokenProvider.GetAccessTokenAsync("https://<mywebapi>.azurewebsites.net").GetAwaiter().GetResult();
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", accessToken);
RemoteIp = httpClient.GetStringAsync("https://<mywebapi>.azurewebsites.net/api/default/remoteIp").GetAwaiter().GetResult();
LocalIp = httpClient.GetStringAsync("https://<mywebapi>.azurewebsites.net/api/default/localIp").GetAwaiter().GetResult();
ConnectionId = httpClient.GetStringAsync("https://<mywebapi>.azurewebsites.net/api/default/connectionId").GetAwaiter().GetResult();
}
And here is the error message:
Parameters: Connectionstring: [No connection string specified], Resource: https://<mywebapi>.azurewebsites.net, Authority: .
Exception Message: Tried to get token using Managed Service Identity.
Unable to connect to the Managed Service Identity (MSI) endpoint.
Please check that you are running on an Azure resource that has MSI setup.
UPDATE:
<mywebapi> is obviously the actual endpoint value, but not exposed here on stackoverflow. Furthermore I should mention that calling the API endpoints directly works fine, after I have authorized with my personal credentials xxx#xxx.xxx. The issue is related to the webapp trying to identify itself to the webapi, even though it is a registered application which has been assigned the necessary IAM rights on the webapi resource.
The error says it tried to use MSI, but could not. Are you sure you are running this code on the Web App with MSI enabled?
Also, you need to replace "https://<mywebapi>.azurewebsites.net" with the App Id URI or Application Id of your API in Azure AD.
In other words, this needs to match the valid audience that you have configured for the API.

Simple Directory Lookup in Azure Active Directory

I am writing a simple desktop application that needs to retrieve some basic properties about a user from Microsoft’ directory. Specifically:
I am writing a single tenant native LOB application.
The application runs on my desktop.
The application runs as my logged on domain account.
The organization' domain accounts are synced to AAD.
I am not trying to secure a native web app or a Web API or anything like that. I do not need users to sign in.
I have email addresses of folks in my organization from an external event management tool. I need to lookup the AAD account profile data (address book info - specifically job title) from AAD based on the email address. I will only be reading AAD data.
So far, I have done the following:-
It appears that the Azure AD Graph API is the right way to fetch the profile information. In particular, the information is available at the endpoint: https://graph.windows.net/{tenant}/users/{email}?api-version=1.6
When registering the native application in AAD, no key was provided. So I don't have a client secret.
Looked at the sample in GitHub here: https://github.com/Azure-Samples/active-directory-dotnet-graphapi-console. The instructions here seem to be wrong because no Keys section is available [see (2)].
Based on the sample above, I wrote a simple function. Code is below:
private static async Task PrintAADUserData(string email)
{
string clientId = "0a202b2c-6220-438d-9501-036d4e05037f";
Uri redirectUri = new Uri("http://localhost:4000");
string resource = "https://graph.windows.net/{tenant}";
string authority = "https://login.microsoftonline.com/{tenant}/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authority);
AuthenticationResult authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
string api = String.Format("https://graph.windows.net/{tenant}/users/{0}?api-version=1.6", email);
LOG.DebugFormat("Using API URL {0}", api);
// Create an HTTP client and add the token to the Authorization header
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authResult.AccessTokenType, authResult.AccessToken);
HttpResponseMessage response = await httpClient.GetAsync(api);
string data = await response.Content.ReadAsStringAsync();
LOG.Debug(data);
}
Questions
The application when run was able to bring up the authentication page. Why do I need that? The application already runs as my domain account. Is an additional authentication necessary? If I were to run this application in Azure as a worker process, then I would not want to use my domain credentials.
The primary problem seems to be the resource URL which is wrong. What resource do I need to specify to access the Azure AD Graph API?
Thanks,
Vijai.
EDITS
Based on the comments from #Saca, the code and application has been edited.
Code
string clientId = ConfigurationManager.AppSettings["AADClientId"];
string clientSecret = ConfigurationManager.AppSettings["AADClientSecret"];
string appIdUri = ConfigurationManager.AppSettings["AADAppIdURI"];
string authEndpoint = ConfigurationManager.AppSettings["AADGraphAuthority"];
string graphEndpoint = ConfigurationManager.AppSettings["AADGraphEndpoint"];
AuthenticationContext authContext = new AuthenticationContext(authEndpoint, false);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.windows.net", new ClientCredential(clientId, clientSecret));
ExistingTokenWrapper wrapper = new ExistingTokenWrapper(authResult.AccessToken);
ActiveDirectoryClient client = new ActiveDirectoryClient(new Uri(graphEndpoint), async () => await wrapper.GetToken());
IUser user = client.Users.Where(_ => _.UserPrincipalName.Equals(email.ToLowerInvariant())).Take(1).ExecuteSingleAsync().Result;
App
Error
Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> Microsoft.Data.OData.ODataErrorException: Insufficient privileges to complete the operation. ---> System.Data.Services.Client.DataServiceQueryException: An error occurred while processing this request. ---> System.Data.Services.Client.DataServiceClientException: {"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}
It appears that despite giving the right permissions, the correct resource and being able to acquire a token, there is still something missing.
The key thing to consider here is if your application will be a headless client run from a secure server or desktop client run by users on their machines.
If the former, then your application is considered a confidential client and can be trusted with secrets, i.e. the keys. If this is your scenario, which is the scenario covered by the sample, then you need to use clientId and clientSecret.
The most likely reason you are not seeing a Keys section in the your application's Configure page is that, instead of selecting Web Application and/or Web API as per step #7 in the sample, you selected Native Client Application when first creating the application. This "type" can't be changed, so you'll need to create a new application.
If your scenario is the latter, then your application is considered a public client and can't be trusted with secrets, in which case, your only options is to prompt the user for credentials. Otherwise, even if your app has it's own authorization layer, it can easily be decompiled and the secret extracted and used.
Your resource URL is correct by the way.
Turns out the real issue was not with the code. I am not an AAD administrator. It appears that any application needing to perform authentication against AAD in our tenant needs to have permissions enabled by the AAD administrators. Once they enabled permissions for my application (and took ownership of the AAD registration as well), this started working.
Hope help some one that are using GraphClient:
var userPriNam = "johndoe#cloudalloc.com";
var userLookupTask = activeDirectoryClient.Users.Where(
user => user.UserPrincipalName.Equals(userPriNam, StringComparison.CurrentCultureIgnoreCase)).ExecuteSingleAsync();
User userJohnDoe = (User)await userLookupTask;
from https://www.simple-talk.com/cloud/security-and-compliance/azure-active-directory-part-5-graph-api/

Azure AD Sign In

I have a web application that is secured by Azure AD. I would like to be able to allow some people to access this application. I have created an account in my directory for these users and I would like to log them in without doing a redirect to Azure AD.
Is there any way to get an Azure auth cookie and allow them to access my application without redirecting them to a login? I know the username / password and would like to be able to do the sign in behind the scenes.
You should be able to use the Resource Owner Credentials flow. Assuming you're using ADAL, you can leverage this sample app to retrieve a token.
Once you have the authentication result, you can use it to build an identity and pass that to the cookie authentication manager (assuming you're using the OWIN cookie authentication middleware).
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.GivenName, result.UserInfo.GivenName));
var id = new ClaimsIdentity(claims,
DefaultAuthenticationTypes.ApplicationCookie);
var ctx = Request.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(id);
Source: http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/

Resources