rest api unauthorized Azure Data Catalog - rest

I am using Azure Data Catalog of my organization. I am not creator/administrator/owner of the Catalog but I have access to register/delete catalogs from the web interface.
I want to use rest API for Azure Data Catalog. Is it possible with my level of permission?
I have followed all the steps from https://msdn.microsoft.com/en-us/library/mt428033.aspx and written the following piece of code:
class Program
{
static void Main(string[] args)
{
string url = "https://api.azuredatacatalog.com/catalogs/DefaultCatalog/search/search?searchTerms=My_Server&count=10&startPage=1&api-version=2016-03-30";
HttpWebRequest request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
Console.WriteLine(AccessToken().CreateAuthorizationHeader());
try
{
WebResponse response = request.GetResponse();
Console.WriteLine(response.ContentLength);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
static AuthenticationResult AccessToken()
{
string resourceUri = "https://datacatalog.azure.com";
string clientId = "my-client-id";
string redirectUri = "my-redirect-uri";
string authorityUri = "https://login.windows.net/common/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
return authContext.AcquireToken(resourceUri, clientId, new Uri(redirectUri), PromptBehavior.RefreshSession);
}
}
and when I try to run the search from API, I get the following error:
System.Net.WebException: The remote server returned an error: (401)
Unauthorized. at System.Net.HttpWebRequest.GetResponse() at
HRBIADCAPI.Program.Main(String[] args) in
c:\users\naghimir\documents\visual studio
2015\Projects\HRBIADCAPI\HRBIADCAPI\Program.cs:line 32
Now I think the problem is that I have not given access to the client program created to read/write data catalog (that I did in Azure Data Factory) but that step is not there in the documentation either.
Do I need to be the owner or can I request permission from the owner to use Azure Data Catalog API?

Based on the description, you were using the OAuth 2.0 code grant flow to grant the app to delegate the user to manipulate the Azure Data Catalog.
To ensure the request works well, we need to grant the scope to the app like figure below:
And since the app only delegate the users’ permission, please ensure that user have the sufficient permission to operate the resource manfully.

Related

Need example showing OAUTH2 connection to Microsoft Exchange in JavaMail

I am trying to write a basic program in Java, using JavaMail, to send an email using Microsoft's new OAUTH2 mechanism.
On StackOverflow, I found the following code via a link, but it does not authenticate given a current access token:
public static void main(String[] args) throws IOException, MessagingException
{
Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
String userEmail = "email_account_here";
String accessToken = access_token_here"
store.connect("imap-mail.outlook.com",993,userEmail, accessToken);
session.setDebug(true);
}
I am generating the token using a call to the Microsoft Graph API (not using JavaMail).
Result is "Authentication Failed".
I have searched but cannot find an example that works.
Would appreciate any code samples that work. :)
Thanks!

DefaultAzureCredential: Graph access forbidden with VisualStudio Code Credential

I'm trying to read user properties from ms graph inside an Azure function.
For authentication I used the DefaultAzureCredential class from Azure.Identity.
Access with Shared Token Cache Credential locally and Managed Identity Credential in Azure is no prob!
I wanted to use the Visual Studio Code Credential, but I get an "Authorization_RequestDenied! Insufficient privileges to complete the operation" error message when I call the graph API.
The problem seems to be the access token I received with the VS Code Credential. The user account is the same one I used with the Shared Token Cache Credential.
Any ideas? Thank you.
Code:
DefaultAzureCredentialOptions options = new DefaultAzureCredentialOptions();
options.VisualStudioCodeTenantId = Environment.GetEnvironmentVariable("Debug_VisualStudioCodeTenantId");
var credential = new DefaultAzureCredential(options);
token = credential.GetToken(
new Azure.Core.TokenRequestContext(
new[] { "https://graph.microsoft.com/.default" }));
accessToken = token.Token;
var graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage
.Headers
.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.CompletedTask;
}));
var users = await graphServiceClient.Users.Request().GetAsync(); // throw the forbidden exception
Exception:
"Code: Authorization_RequestDenied\r\nMessage: Insufficient privileges to complete the operation.\r\nInner error:\r\n\tAdditionalData:\r\n\tdate: 2021-04-20T08:02:23\r\n\trequest-id: ...\r\n\tclient-request-id: ...\r\nClientRequestId: ...\r\n"
After inspecting the token returned by VS Code, it seems to be missing a required delegated permission/scope.
The docs say one of these is required to list users:
User.ReadBasic.All, User.Read.All, User.ReadWrite.All, Directory.Read.All, Directory.ReadWrite.All, Directory.AccessAsUser.All
Since the service principal that VS Code is using does not require any of these, it won't work.
After trying to explicitly get the token with the required scope, it doesn't seem to work either.
So the VS Code credential currently just doesn't seem to work for this purpose.
You'll need a different credential or perhaps use the client secret/certificate credential with your own app registration.

How to Identify caller when grant_type is client_credentials?

I have ASP.NET Web application and I am using IdentityServer3 for user authentication. Our customers login to web application using userid/password.
Now I have one more Web API and some of our customers need to call this web api from their applications. (server to server communication). So based on this, in identityserver i did the following
1> Created a new scope name api
2> Created a new client for Web API and configured with allowed scope api and offline_access
3> Set flow to ClientCredentials
4> Set AccessTokenType to Jwt
5> For each customer i created different secret key
Now our customers can get access token at connect/token endpoint and then make call to API using the access token. The API validates the token with IdentityServer, and then returns the result. All good till here.
However, in API project i also need to identify the customer aka caller. Based on customer i need to do some logic
public class ResourcesController : ApiController
{
public IHttpActionResult Get()
{
var caller = User as ClaimsPrincipal;
// need to identify caller here
return Json(new
{
message = "OK",
});
}
}
(One option i can think of is taking customer id is as part of API url. Something like http://api.domain.com/v1/customerid/resources)
Is there anyway to make a use of IdentityServer to identify customer?
I've actually had a similar need some time ago. For the simplest solution, you should be able to assign a custom claim to each of the Identity Server client that you have created for your customers.
AlwaysSendClientClaims = true,
Claims = new List<Claim>()
{
new Claim("CustomerId", "0121021")
}
These client claims will then be included in the access token and therefore available to you in your backend.
public class ResourcesController : ApiController
{
public IHttpActionResult Get()
{
var caller = User as ClaimsPrincipal;
// need to identify caller here
var customerId = caller?.Claims.Where(p => p.Type.Equals("CustomerId")).First().Value;
// need to identify caller here
return Json(new
{
message = "OK",
});
}
}

Servicenow Rest API call to check if credentials are valid

I am calling ServiceNow Rest API for tables in my application. I allow the user to enter their servicenow instance credentials and domain url in my application.
I want to know if there is a Simple API call which I can make to ensure that the credentials entered are valid.
Currently I am making a call to get sys_user table and making the check.
This call seems to take more time. Is there a simpler REST URL which I can use here?
public static HttpConnectionResponse checkConnection(String host, String username, String password) {
String CHECK_URL = "/api/now/table/sys_user";
HttpConnectionResponse response = new HttpConnectionResponse();
String completeUrl = "https://"+host+CHECK_URL;
HashMap<String, String> requestHeaders = ConnectionUtils.getDefaultInputHeader();
Credential credential = ConnectionUtils.populateCredentials(username, password);
try{
response = HttpConnectorClient.getMethod(completeUrl, requestHeaders, credential);
}
catch(Exception e){
e.printStackTrace();
}
return response;
}
Why not just use any table or record that you've set to be accessible to any authenticated user, then make a REST API call with their credentials as the basic authentication credentials, to that resource? If you get the record rather than "access denied", the creds are valid. :-)
You could even make a simple UI page, or better yet, a Processor, just for that purpose.

List Storage Accounts only listing a few classic storage accounts

List Storage Accounts https://management.core.windows.net//services/storageservices
says that it lists the storage accounts that are available in the specified subscription and the get storage account keys work only for these storage accounts that are returned as part of this call.
But the response is giving me only few storage accounts which are classic, how do i get the other storage accounts?
But the response is giving me only few storage accounts which are
classic, how do i get the other storage accounts?
By "other" storage accounts, I guess you're meaning "Azure Resource Manager (ARM)" storage accounts. There's a different API to get ARM storage accounts that make use of Azure AD based authentication.
To learn more about ARM API to list storage accounts, please see this link: https://learn.microsoft.com/en-us/rest/api/storagerp/storageaccounts#StorageAccounts_List.
To learn more about how to authenticate/authorize ARM API calls, please see this link: https://learn.microsoft.com/en-us/rest/api/
I agree with Gaurav Mantri, if you’d like to list ARM storage accounts under a specified subscription, please use this API:
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Storage/storageAccounts?api-version=2016-12-01
And the following code sample works fine on my side, please refer to it.
string tenantId = "{tenantId}";
string clientId = "{clientId}";
string clientSecret = "{secret}";
string subscriptionid = "{subscriptionid}";
string authContextURL = "https://login.windows.net/" + tenantId;
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential(clientId, clientSecret);
var result = await authenticationContext.AcquireTokenAsync(resource: "https://management.azure.com/", clientCredential: credential);
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://management.azure.com/subscriptions/{0}/providers/Microsoft.Storage/storageAccounts?api-version=2016-12-01", subscriptionid));
request.Method = "GET";
request.Headers["Authorization"] = "Bearer " + token;
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
//extract data from response
}
catch (WebException ex)
{
//ex.Message;
}
Besides, this article explained how to create AD application and service principal that can access resources, please refer to it.
Thanks for your response,by other storage accounts I meant the storage accounts under the classic storage accounts itself which were not getting listed.
Instead of using
https://management.core.windows.net//services/storageservices
I used the REST API's
for the new storage accounts
/management.azure.com/subscriptions/id/providers/Microsoft.Storage/storageAccounts?api-version=2016-12-01
for classic:
/management.azure.com/subscriptions//providers/Microsoft.ClassicStorage/storageAccounts?api-version=
and to get keys
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}/listKeys?api-version=2016-12-01
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ClassicStorage/storageAccounts/{accountName}/listKeys?api-version=2016-11-01