Using GraphServiceClient to retrieve group info of Azure Ad members - asp.net

i want to retrieve all members of a Azure Ad group within my backend application. I followed the steps here and here and here is my code:
But I always get this error when using the method:
Microsoft.Graph.ServiceException: Code: generalException Message: An
error occurred sending the request.
---> Microsoft.Graph.Auth.AuthenticationException: Code:
authenticationChallengeRequired Message: Authentication challange is
required.
Can someone help me with that? I didn't find this specific error.

Obviously these parameters(clientId/tenantId/clientSecret/groupId) need to be replaced with specific strings.
You could find clientId and tenantId via App registrations-> Overview:
clientSecret via App registrations-> Certificates & secrets:
groupId via Azure Active Directory -> Groups:
You could also store the specific strings in a profile and read the strings in the file.
And the sample will help you to understand it.
AccountController.cs :
IConfidentialClientApplication daemonClient;
daemonClient = ConfidentialClientApplicationBuilder.Create(Startup.clientId)
.WithAuthority(string.Format(AuthorityFormat, tenantId))
.WithRedirectUri(Startup.redirectUri)
.WithClientSecret(Startup.clientSecret)
.Build();
Web.config :
<add key="ida:ClientId" value="[Enter your client ID]" />
<add key="ida:ClientSecret" value="[Enter your client secret]" />
Startup.Auth.cs :
public static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
public static string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
public static string redirectUri = "https://localhost:44316/";

did you register an app registration in azure ad, create a secret, set the proper api permissions?
there are even quickstarts in the app registration portal that helps you configure the code and give you a pre set up project that you can experiment with.
Also your code seems to be missing scopes, you need to request the appropriate scopes for graph api token to access groups.
I think the documentation here is better: https://github.com/microsoftgraph/msgraph-sdk-dotnet-auth
and if you check the unit tests here for authorization code flow: https://github.com/microsoftgraph/msgraph-sdk-dotnet-auth/blob/dev/tests/Microsoft.Graph.Auth.Test/ConfidentialClient/AuthorizationCodeProviderTests.cs
gives you a good example of how to make it work.

Related

Getting "Missing or malformed Token" while using gofiber firebase-auth

I am trying to run Gofiber firebase-auth. I have generated a private key from Firebase Console, Settings -> Service Account -> Generate new private key and have given the file path to:
.env:
GOOGLE_SERVICE_ACCOUNT = 'C:/Users/Desktop/flutter-demo.json'
WEB_API_KEY = "<API_KEY>" // from config section of general settings at firebase console
TEST_USER_EMAIL = "test#test.com"
TEST_USER_PASSWORD = "test123"
which is used in main.go:
serviceAccount, fileExi := os.LookupEnv("GOOGLE_SERVICE_ACCOUNT")
opt := option.WithCredentialsFile(serviceAccount)
But, on accessing any of the Authenticated Routes, I'm getting:
Missing or malformed Token
Can anyone please help, maybe I'm doing some mistake or missing something from the docs
Hi below is an example of using gofiber firebase auth,
https://github.com/gofiber/recipes/tree/master/firebase-auth
Hope this will help you. Thanks
Thanks to Sachintha, one needs to send an Authorization Header token from login with the user name and password, as go firebase auth just a middleware to check whether endpoints are authenticated and it does not provide any authentication or user login.

ADFS 2016 On behalf of flow : cannot get any user informations

I'm trying to implement the "on behalf of" flow in an application using ADFS 2016 as STS. As a reference, I look at this Microsoft tutorial (https://learn.microsoft.com/en-ca/windows-server/identity/ad-fs/development/ad-fs-on-behalf-of-authentication-in-windows-server). It's working as it should, I can login into my web application and then use my original access token in UserAssertion to generate a new access token with the proper audience to call my API BUT I found absolutely no way to include any user informations (sub, name, email, upn etc.) into the access token for my API, even if I set claim rules into my ADFS configurations for the API.
I checked the communication between my app and adfs using Fiddler and everything looks like the informations in the tutorial. See the screen shot of the "on behalf of" request below :
Here's the resulting access token :
Finally, here's the code I use to generate my new access token :
private async Task<string> GetAccessToken(ClaimsPrincipal user, string originalAccessToken)
{
var authority = "[authority]";
var context = new AuthenticationContext(authority, false);
string userName = user.FindFirstValue("upn");
var userAssertion = new UserAssertion(originalAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer",userName);
var cc = new ClientCredential("https://localhost:44387/", "[client_secret]");
var result = await context.AcquireTokenAsync("https://localhost:44339/", cc, userAssertion);
return result.AccessToken;
}
Have you struggle with that scenario and if yes, did you find a way to fix this ?
Thanks
I've only used the Microsoft On Behalf Of flow with Azure AD and not ADFS, but it looks like you need to send a more detailed scope in your User Info request.
Maybe try sending 'openid profile email', to indicate that you want that type of detail, as in Section 17 of my blog post. Of course this assumes that this type of data has been registered for all users.
TROUBLESHOOTING
Looks like one of these will be the cause:
A suboptimal Microsoft library that does not allow you to send the required scope
Or ADFS 2016 perhaps lacks the scope features that work correctly in Azure AD
I would concentrate on making extra sure you are sending the correct form URL encoded request message, using a tool such as curl, Postman or a plain C# HttpClient. Here is the code I used to send the correct scope - using an open source library rather than a Microsoft one:
Sample NodeJS Code
If you can get the scope sent correctly then you should have a resolution either way:
Either you get the correct data and can update your code
Or the behaviour you want is not supported by ADFS
Good luck ...

Exception using Azure Managed Service Identity across tenants

I'm building an Azure web app for a client that will be provisioned into many other directories for their customers. This app will call a web API in my client's directory, which will then call back to another web API in the customer's directory. Something like this:
Other Customer AAD1 --------- My client AAD2
App --------------------------------> Web API 2
Web API 1 <-------------------------- Web API 2
We have been able to get the first call to work. This requires a corresponding App Registation for Web API 2 in AAD1. We figure that we could get the callback to work by following the same pattern, with a registration for Web API1 in AAD2. However, that might be a LOT of these 'proxy' registration in my client's AAD, so we're looking at alternatives.
We are exploring using Managed Service Identity, which we think will allow us to get tokens that are valid for resources in other tenants. If there's a better way, I'm certainly interested in knowing about it.
I've followed the code example from here using the Microsoft.Azure.Services.AppAuthentication library: https://learn.microsoft.com/en-us/azure/app-service/app-service-managed-service-identity#obtaining-tokens-for-azure-resources
// In Web API 2
using Microsoft.Azure.Services.AppAuthentication;
// ...
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(
"https://<App ID URI for Web API1>");
Web API2 is configured to have a Managed Service Identity.
I'm currently running this on my local machine, and I've installed Azure CLI and I'm logged in. I've tried 'az account get-access-token', and I get a valid token.
When Web API2 tries to get the token to be able to call Web API1, I get an exception:
Parameters: Connectionstring: [No connection string specified], Resource: , Authority: . Exception Message: Tried the following 2 methods to get an access token, but none of them worked.
Parameters: Connectionstring: [No connection string specified], Resource: , 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.
Parameters: Connectionstring: [No connection string specified], Resource: , Authority: . Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. ERROR: Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Web API 1'. Send an interactive authorization request for this user and resource.\r\nTrace ID: f5bb0d4d-6f92-4fdd-81b7-e82a78720a00\r\nCorrelation ID: 04f92114-8d9d-40c6-b292-965168d6a919\r\nTimestamp: 2017-10-19 16:39:22Z","error_codes":[65001],"timestamp":"2017-10-19 16:39:22Z","trace_id":"f5bb0d4d-6f92-4fdd-81b7-e82a78720a00","correlation_id":"04f92114-8d9d-40c6-b292-965168d6a919"}
What's interesting is that there's no application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' in either AAD1 or AAD2. Is this a known Azure app? I thought that it might be the Service Management API, but I'm not sure.
In any case, I'm not sure of the proper way to grant permission. I've tried building different content URLs like this into my browser, but none of them seem to have done the trick:
https://login.microsoftonline.com/(AAD1 ID)/adminconsent
?client_id=(App ID)
&redirect_uri=https://localhost:44341
&resource=(App ID URI for Web API1)
&prompt=admin_consent
https://login.microsoftonline.com/(AAD1 ID)/adminconsent
?client_id=04b07795-8ddb-461a-bbee-02f9e1bf7b46
&redirect_uri=https://localhost:44341
&resource=(App ID URI for Web API1)
&prompt=admin_consent
(This last one tells me that the reply URL is incorrect; since it's not one of my apps, I can't find the reply URL)
Note that the tenant is AAD1.
Am I missing something, or am I not using this feature correctly?
Thanks in advance.
AzureServiceTokenProvider uses Azure CLI (among other options) for local development. For a scenario where a service calls an Azure Service, this works using the developer identity from Azure CLI, since Azure services allow access to both users and applications.
For a scenario where a service calls another custom service (like your scenario), you need to use a service principal for local development. For this, you have two options:
Login to Azure CLI using a service principal.
First, create a service principal for local development
https://learn.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest
Then login to Azure CLI using it.
az login --service-principal -u 25922285-eab9-4262-ba61-8083533a929b --password <<pwd>> --tenant 72f988bf-86f1-41af-91ab-2d7cd011db47 --allow-no-subscriptions
Use the --allow-no-subscriptions argument since this service principal may not have access to any subscription.
Now, AzureServiceTokenProvider will get a token using this service principal for local development.
Specify service principal details in an environment variable. AzureServiceTokenProvider will use the specified service principal for local development. Please see the section Running the application using a service principal in local development environment in this sample on how to do that. https://github.com/Azure-Samples/app-service-msi-keyvault-dotnet
Note: Ths is only for local development. AzureServiceTokenProvider will use MSI when deployed to App Service.

How to pass user authentication of a private dataset through SODA API?

I need to access a private data set in socrata using SODA API. Suppose below link is the data set
https://data.cityofchicago.org/resource/xxxx-xxx.json
I get the following error when try this.
"error" : true,
"message" : "You must be logged in to access this resource"
I have valid credentials to access the data set. But how can I pass it through SODA API calls?
I tried the below code but it doesn't work.
https://data.cityofchicago.org/resource/xxxx-xxx.json?$username='myname'&$password='pwd#123'
You'll need to use either HTTP Basic or OAuth 2.0 to authenticate. We have details on how to do that on the developer portal.
Make sure you also provide an application token, as detailed in those docs.
You need to pass Secret-Token and AppToken with the query string.
How to Get secret Token
Log in to your portal and select "Create new Application"
Enter https://data.cityofchicago.org/resource/xxxx-xxx.json in the "website" field.
Save it.
Go to "Manage" and get your AppToken and SecretToken from under "Manage".
Now, pass the app token and secret token in the URL according to socrata developer document syntax:
https://sandbox.socrata.com/oauth/access_token
?client_id=YOUR_AUTH_TOKEN
&client_secret=YOUR_SECRET_TOKEN
&grant_type=authorization_code
&redirect_uri=YOUR_REDIRECT_URI
&code=CODE
I am also looking for an answer for the same question. After passing the app token I can access public DB but can not access Private DB.

Novell eDirectory with .NET DirectoryServices

In our company, we have a project which should use Novell eDirectory with .net applications.
I have tried Novell Api (http://www.novell.com/coolsolutions/feature/11204.html) to connect between .NET applications. It is working fine.
But, as per requirement, we specifically need .net API to connect not with Novell Api, which is not working. Connection and binding with .NET Api DirectoryServices not working.
Our Novell eDirectory is installed with following credentials:
IP address: 10.0.x.xx(witsxxx.companyname.com)
Tree : SXXXX
New Tree Context: WIxxxK01-NDS.OU=STATE.O=ORG
ADMIN Context is: ou=STATE,o=ORG
admin : admin
password: admin
I used Novell Api and used following code
String ldapHost ="10.0.x.xx";
String loginDN = "cn=admin,cn=WIxxxK01-NDS,OU=STATE,o=ORG";
String password = string.Empty;
String searchBase = "o=ORG";
String searchFilter = "(objectclass=*)";
Novell.Directory.Ldap.LdapConnection lc = new Novell.Directory.Ldap.LdapConnection();
try
{
// connect to the server
lc.Connect(ldapHost, LdapPort);
// bind to the server
lc.Bind(LdapVersion, loginDN, password);
}
This is binding correctly and searching can be done.
Now my issue is with when I trying to use .NET APi and to use System.DirectoryServices
or System.DirectoryServices.Protocols, it is not connecting or binding.
I can't even test the following DirectoryEntry.Exists method. It is going to exception.
string myADSPath = "LDAP://10.0.x.xx:636/OU=STATE,O=ORG";
// Determine whether the given path is correct for the DirectoryEntry.
if (DirectoryEntry.Exists(myADSPath))
{
Console.WriteLine("The path {0} is valid",myADSPath);
}
else
{
Console.WriteLine("The path {0} is invalid",myADSPath);
}
It is saying Server is not operational or Local error occurred etc. I don't know what is happening with directory path.
I tried
DirectoryEntry de = new DirectoryEntry("LDAP://10.0.x.xx:636/O=ORG,DC=witsxxx,DC=companyname,DC=com", "cn=admin,cn=WIxxxK01-NDS,o=ORG", "admin");
DirectorySearcher ds = new DirectorySearcher(de, "&(objectClass=user)");
var test = ds.FindAll();
All are going to exceptions.
Could you please help me to solve this? How should be the userDN for DirectoryEntry?
I used System.DirectoryServices.Protocols.LdapConnection too with LdapDirectoryIdentifier and System.Net.NetworkCredential but no result. Only same exceptions.
I appreciate your valuable time and help.
Thanks,
Binu
To diagnose your LDAP connection error, get access to the eDirectory server from the admins, and use iMonitor (serverIP:8028/nds and select Dstrace), in Dstrace clear all tabs and enable LDAP tracing, then do your bind see what happens on the LDAP side to see if there is a more descriptive error there. Or if you even get far enough to bind and make a connection.

Resources