I want to pull data from Yammer via Avocado Api where in all views are created in api, I followed below link however I 'm not able to authenticate and secondly there is not code to pull data from avocado rest api, could you please help me with some code.
here is the api link for reference
https://avocadowiki.azurewebsites.net/wiki/Backend_API_Client_Examples
here is the reports link
https://avocado/
According to your description, I followed this avocado-console-client sample to test it on my side. I could make it work as expected, you could refer to the steps below:
1.Update Microsoft.IdentityModel.Clients.ActiveDirectory to the latest stable version (3.13.8) via NuGet
2.Modify the function authCtx.AcquireToken to authCtx.AcquireTokenAsync as follows:
var authResult = await authCtx.AcquireTokenAsync(avocadoResourceUri, thisConsoleAppClientId, thisConsoleAppUri, new PlatformParameters(PromptBehavior.Auto));
3.Register your native app and modify thisConsoleAppClientId and thisConsoleAppUri
Sign in to the Azure Portal, click "Azure Active Directory" > "App registrations", click Add buttion to add your native app as follows:
For thisConsoleAppClientId(your client app Id), you could find it on Azure Portal:
For thisConsoleAppUri (the return url of your app):
Note: In order to access Avocado API, you need to assign your app with the delegated permission to Avocado. You could follow the steps below:
Select you AD app on Azure, In the Settings blade click "Required permissions" to add a permission and choose "Have full access to the service" option.
Note: You could input Avocado [wsfed enabled] to select the Avocado API.
Upon the configurations, you could test it. Here is my code snippet:
Program.cs
class Program
{
static void Main(string[] args)
{
AvocadoDemo();
Console.WriteLine("press any key to exit...");
Console.ReadKey();
}
static async Task AvocadoDemo()
{
string thisConsoleAppClientId = "c588cf8d-8651-4b37-8d10-49237cf92f8e";
Uri thisConsoleAppUri = new Uri("http://bruceConsoleForAvocado");
string avocadoResourceUri = "https://microsoft.onmicrosoft.com/Avocado";
// Get the access token for Avocado. This will pop up the login dialog and consent page for the first time.
// Then the token will be cached in the FileCache, and AcquireToken will renew the token automatically in the subsequent run.
AuthenticationContext authCtx = new AuthenticationContext("https://login.windows.net/microsoft.onmicrosoft.com", new FileCache());
var authResult = await authCtx.AcquireTokenAsync(avocadoResourceUri, thisConsoleAppClientId, thisConsoleAppUri, new PlatformParameters(PromptBehavior.Auto));
if (!string.IsNullOrEmpty(authResult.AccessToken))
Console.WriteLine("accessToken: " + authResult.AccessToken);
// call Avocado API
var baseAddress = new Uri("https://avocado");
var cookieContainer = new CookieContainer();
// POSTing a new execution will invoke a redirect, so for example purposes we are disabling it here.
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer, AllowAutoRedirect = false })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
// Need to set this cookie for avocado api to work.
cookieContainer.Add(baseAddress, new Cookie("deep_link", "-1"));
// add your access token in the header
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
// Here's a GET example
var avoResultGet = client.GetAsync("/schedules/7215.json").Result;
var strGet = avoResultGet.Content.ReadAsStringAsync().Result;
Console.WriteLine("Avocado API returns: " + strGet);
}
}
}
Result
Since you have been authenticated, you could refer to API Documentation to invoke the specific APIs as you wish.
Related
I'm developing a c# windows forms app that needs to authenticate using the Implicit Flow (The client does not accept another flow). As requirement, I need to open the default system browser to authenticate (so no embedded web view on the application)
I'm trying to use the OidcClient C# and the Samples but I can't get it to work.
The closest I got was using the ConsoleSystemBrowser. But using the code below I get always an UnknownError with empty response.
I can see in the browser the id_token: http://127.0.0.1:54423/auth/signin-oidc#id_token=XXX. How can I read it?
var browser = new SystemBrowser();
var redirectUri = string.Format($"http://127.0.0.1:{browser.Port}/auth/signin-oidc");
var options = new OidcClientOptions
{
Authority = "https://demo.identityserver.io",
ClientId = "implicit",
Scope = "openid profile api",
RedirectUri = redirectUri,
Browser = browser
};
var client = new OidcClient(options);
var state = await client.PrepareLoginAsync(new Dictionary<string, string>()
{
{ OidcConstants.AuthorizeRequest.ResponseType, OidcConstants.ResponseTypes.IdTokenToken}
});
var browserOption = new BrowserOptions(state.StartUrl, redirectUri)
{
Timeout = TimeSpan.FromSeconds(300),
DisplayMode = DisplayMode.Hidden,
ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect
};
var result = await browser.InvokeAsync(browserOption, default);
result.ResultType => BrowserResultType.UnknownError
Your application should register a private URL scheme with the networking component of the OS. Then, URLs of the form "x-my-app://xxx" will be forwarded to your application. (And you register the URL with the OAuth IdP so it works as a redirect URL.)
For Windows, it appears that Microsoft calls this "Pluggable Protocols". See
programming-pluggable-protocols
An older doc
A source of code examples for this pattern might be from the github desktop application--it is open source and registers its own scheme with Windows.
It registers the private scheme x-github-client You can see how it's done in the source also see here
Currently having issues integrating Microsoft Graph API, into my ASP.NET Core 2.2 Web Application(MVC). That uses "Work or Schools Accounts" : “Cloud – Single Organisation” using Two Factor Azure Sign-on Authentication.
Using Code Sample 1 code I'm attempting to GET the graph query: -
https://graph.microsoft.com/v1.0/me/
returning the surname from the response header
The issue that i'm experiencing at the moment is that i'm receiving an error at the line of code: -
var objMessages = objGraphClient.Me.Request().GetAsync().Result;
With the error message : "does not exist or one of its queried reference-property objects are not present".
// #############
// Code Sample 1
// #############
// Graph Api.
string strResource = "https://graph.microsoft.com";
string SecretId = "<Secret Id>";
// Azure Ad.
Uri strInstance = new Uri("https://login.microsoftonline.com/");
string strDomain = "<Domain>.onmicrosoft.com";
string strTenantId = "<Tenant Id>";
string strClientId = "<Client Id>";
string strCallbackPath = "/signin-oidc";
// The authority to ask for a token: your azure active directory.
string strAuthority = new Uri(strInstance, strTenantId).AbsoluteUri;
AuthenticationContext objAuthenticationContext = new AuthenticationContext(strAuthority);
ClientCredential objClientCredential = new ClientCredential(strClientId, SecretId);
// Acquire Token.
AuthenticationResult objAuthenticationResult = objAuthenticationContext.AcquireTokenAsync(strResource, objClientCredential).Result;
// Get bearer token.
GraphServiceClient objGraphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async request =>
{
// This is adding a bearer token to the httpclient used in the requests.
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", objAuthenticationResult.AccessToken);
}));
// The next line produces an error :: does not exist or one of its queried reference-property objects are not present.
var objResult = objGraphClient.Me.Request().GetAsync().Result;
Debug.WriteLine($"{objResult.Surname}");
If I change Code Sample 1 above to Code Sample 2 below passing in the tokenPlease() requested that’s obtained from Microsoft Graph Explorer after successful login, this works, returning the surname successfully, indicating that their is an issue possible in my Bearer token: -
// #############
// Code Sample 2
// #############
// Get bearer token.
GraphServiceClient objGraphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async request =>
{
// This is adding a bearer token to the httpclient used in the requests.
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer","ERf54f2f...Etc");
}));
// The next line now works.
var objResult = objGraphClient.Me.Request().GetAsync().Result;
Debug.WriteLine($"{objResult.Surname}");
Any help on this would be much appreciated!
You are using the ADAL library which uses the old Azure AD V1 authentication endpoint. You should be using the MSAL Library which uses the Azure AD V2 authentication endpoint.
I would suggest making your life easy and go grab the Microsoft.Graph.Auth Nuget package and then use this code instead of having to create your own
DelegateAuthenticationProvider
IConfidentialClientApplication clientApplication = AuthorizationCodeProvider.CreateClientApplication(clientId, redirectUri, clientCredential);
AuthorizationCodeProvider authenticationProvider = new AuthorizationCodeProvider(clientApplication, scopes);
I'm executing the following C# magic and read the token obtained in jwt.io. All's looking great.
DiscoveryResponse vasco = DiscoveryClient.GetAsync("http://localhost:5100").Result;
string tokenUri = vasco.TokenEndpoint;
TokenClient client = new TokenClient(vasco.TokenEndpoint, "Blopp", "SuperSecret");
TokenResponse cred = client.RequestClientCredentialsAsync("secured_api").Result;
string token = cred.AccessToken ?? "none!";
However, it seems not to be entirely well functioning one, because when pasted into Postman using key Authorization and value Bearer + token (the prefix daded manually), I get into the service not being reachable (as discussed in this question).
Using the same credentials on the endpoint http://localhost:5100/connect/token and Postman's OAuth 2.0 based wizard, produces a token that works.
My conclusion's that I somehow don't fetch the proper token using my code (and fail to realize it due to ignorance) or that I fetch a token that's missing something.
How do I fetch the proper token, complete and entirely equivalent to the one that Postman obtains at the URL above?
My conclusion's that I somehow don't fetch the proper token using my code (and fail to realize it due to ignorance) or that I fetch a token that's missing something.
From your codes , you are protecting an API using Client Credentials, so firstly please follow the detailed steps in article to config the identity server , web api and the clients .
For testing , i follow the steps in the article , and use same codes as you shown to acquire token :
// discover endpoints from metadata
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");
'http://localhost:5000' is the identity server's host endpoint and clinet/secret is the credential of my client :
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" }
}
};
}
Use that token to access the web api in Postman :
You can also compare the acquiring token request when using the OAuth 2.0 based wizard and confirm that you are using the client credential flow .
So I believe my APIservice should be fine since I can return results through Swagger? I am calling from a WPF project. I launch the program and it asks me to login, then it continues and will tell me I don't have permission.
I'm super green to WebAPI2 and think I may just be constructing my call incorrectly. It does seem that I get a token back correctly from my site, the only issue is when I try to actually call on the API for data.
Here is my code:
public static string clientId = "{#Calling App Id}";
public static string commonAuthority = "https://login.windows.net/{#my Azure AD tenant}";
public static Uri returnUri = new Uri("http://MyDirectorySearcherApp");
const string ResourceUri = "https://{#Api App Service}.azurewebsites.net";
public static async Task<List<User>> LoadBands(IPlatformParameters parent)
{
AuthenticationResult authResult = null;
List<User> results = new List<User>();
try {
//get token or use refresh
AuthenticationContext authContext = new AuthenticationContext(commonAuthority);
if (authContext.TokenCache.ReadItems().Count() > 0)
authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
authResult = await authContext.AcquireTokenAsync(ResourceUri, clientId, returnUri, parent);
} catch (Exception ee) {
throw ex;
}
using (var httpClient = new HttpClient()) {
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, $"{ResourceUri}/api/Band/")) {
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
using (var response = await httpClient.SendAsync(request)) {
string responseData = await response.Content.ReadAsStringAsync();
//responseData always equals "You do not have permission to view this directory or page"
return results;
}
}
}
Edit: Maybe helpful to note I'm using a DataAPI that is called by a Rest API, the rest API is secured by Azure AD.
Edit: I'm calling from a Portable Class Library.
Edit: Well, I'm getting authenticated but it does not appear to make any difference. If I completely remove the Auth header I get the same result
It seems that the token is incorrect for the web API which protected by Azure AD. Please check the aud claim in the token which should match the Audience you config in the web API project. You can check the aud claim by parse the token from this site.
And if you still have the problem please share the code how you protect the web API.
Update
If you were using the Express mode like below, you need to acquire the access_token using the app which you associate with the web API.
If you were using the Advanced mode, we should also use the that app to acquire the token and the ResourceUri should matched the value you config in ALLOWED TOKEN AUDIENCES like below:
I need a server-side task on my .NET 4.6.1/MVC 5 app that will periodically check a specific O365 email address for new emails and retrieve them if found. This seems like a stupidly simple task, but I cannot find documentation anywhere for creating a server-side process to accomplish this. The only documentation Microsoft seems to have is for OAuth2 and passing through credentials when users sign in. I don't want that. I want to check one specific account, that's it. How would I accomplish this?
These are the pages I've found. There are others, but all are along these lines.
Intro to the Outlook API - I don't see a way to use a service account with the v2 endpoint.
Get Started with the Outlook REST APIs - This is specific to logging users in with OAuth2, unhelpful for my purposes.
Intro to the Outlook API - I don't see a way to use a service account with the v2 endpoint.
The v2 endpoint doesn’t support client credential at present( refer to the limitation). You need to register/configure the app using Azure portal and use the original endpoint to authenticate the app. More detail about register the app please refer to here. And we need to ‘read mail in all mailbox’ to use the client credential to read the messages like figure below.
And here is the code that using client credential to read messages using the Microsoft Graph:
string clientId = "";
string clientsecret = "";
string tenant = "";
string resourceURL = "https://graph.microsoft.com";
string authority = "https://login.microsoftonline.com/" + tenant + "/oauth2/token";
string userMail = "";
var accessToken = new TokenHelper(authority).AcquireTokenAsync(clientId, clientsecret, resourceURL);
var graphserviceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.FromResult(0);
}));
var items = await graphserviceClient.Users[user].Messages.Request().OrderBy("receivedDateTime desc").GetAsync();
foreach (var item in items)
{
Console.WriteLine(item.Subject);
}
class TokenHelper
{
AuthenticationContext authContext;
public TokenHelper(string authUri)
{
authContext = new AuthenticationContext(authUri);
}
public string AcquireTokenAsync(string clientId, string secret,string resrouceURL)
{
var credential = new ClientCredential(clientId: clientId, clientSecret: secret);
var result = authContext.AcquireTokenAsync(resrouceURL, credential).Result;
return result.AccessToken;
}
}
In addition, if we authenticate the app with code grant flow we can also create a subscription which notify the app when the mail box receive the new messages.( refer to webhoocks/subscription)