C# .NetCore Okta Search for Users - okta-api

I am trying to figure out how to search for users in Okta using the SDK and .net core in C#. outside of .net core I am able to do this using Okta.Core but that is not supported in .NET Core. I can't find any documentation for doing this stuff in .NetCore using the SDK.
I can get the OktaClient connected no problem with my API token but after that I am lost now.
Anyone have an example of doing this in Core or can point me in the right direction to get documentation from Okta?

Looking thought the Okta documentation I found the below code, where the client is the Okta client. Hopefully this helps:
Getting A User
// have some user's ID, or login
var someUserId = "<Some User ID String or Login>";
// get the user with the ID or login
var vader = await client.User.GetUserAsync(someUserId);

Related

Can't call Graph API calendars from a daemon application

I am new to the Graph API and would like to call my outlook calendars with the event schedules from a daemon application.
When I login to Microsoft account using the email I use to login to Azure I can see my calendar fine and I can also call the Web API using the Graph Explorer.
E.g. the Graph Explorer call:
https://graph.microsoft.com/v1.0/me/calendars
returns my calendar events fine when I am logged in with my Microsoft account.
Now, I would like to be able to access the same API using a service application i.e. without the user login prompt. So I went to the Azure portal, created and registered a new application, gave it Calendar.Read API permission with the administrator's consent and downloaded a quickstart daemon app which makes
await apiCaller.CallWebApiAndProcessResultASync($"{config.ApiUrl}v1.0/users", result.AccessToken, Display);
call which works i.e. it returns a user so that I can see that the
"userPrincipalName": "XYZ#<formattedemail>.onmicrosoft.com"
which is not what the Graph Explorer call returns. The Graph explorer call:
https://graph.microsoft.com/v1.0/users
and returns "userPrincipalName": "myactualemail"
So basically when I make the Graph Explorer call:
https://graph.microsoft.com/v1.0/me/calendars
it returns the calendars' result which is correct.
However, an equivalent daemon API call
await apiCaller.CallWebApiAndProcessResultASync($"{config.ApiUrl}v1.0/users/f5a1a942-f9e4-460b-9c6c-16f45045548f/calendars", result.AccessToken, Display);
returns:
Failed to call the web API: NotFound
Content: {"error":{"code":"ResourceNotFound","message":"Resource could not be discovered.","innerError":{"date":"2021-12-26T16:46:35","request-id":"67ef50e4-bec6-48ae-9e45-7765436d1345","client-request-id":"67ef50e4-bec6-48ae-9e45-7765436d1345"}}}
I suspect that the issue is in the userPrincipalName mismatch between the Graph Explorer and the daemon application, but I am failing to find a solution to this.
Also note that a normal ASP.NET Core sample which requires manual user login works ok. The issue is only with the daemon application.
There is no "me" in your case, so you need to use https://graph.microsoft.com/v1.0/users/user#domain.demo/calendars url.
When you used Graph Explorer to test the api, you've signed in the website, so /me/calendars contained in the request can know who is me and then return correct data to you.
Come back to your daemon app, we usually use client credential flow to gain the access token/credential to call the api in the daemon so that we don't need to let user sign in and then call the api, this flow makes the app itself can call microsoft graph api. But using this flow will lead to the issue that you can't use me any more because you never signed in yourself, so we should use /users/userPrincipalName/calendars instead.
Then come to the programming module, microsoft provides graph SDK for calling api, this is what you can also see in the api document. You can refer to this document to learn more details about how to use client credential flow with graph SDK. You can also copy my code below.
using Azure.Identity;
using Microsoft.Graph;
public IActionResult Privacy()
{
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_client_id";
var clientSecret = "client_secret";
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var res = graphClient.Users["your_user_id_which_looks_like_xxxx-xxx-xxx-xxxx-xxxxxx"].Calendars.Request().GetAsync().Result;
return View();
}
By the way, if you're not familiar with the flows, you may take a look at my this answer.
I was able to kind of resolve this issue after chatting with the Azure tech guy. It turned out that my Azure account was considered a personal account. And the reason for this apparently was because I was using a personal #yahoo.com email to setup up the Azure account first place. Because of this they would apparently not allow me to purchase o365 and license it. So I had to create a new account with the amazon default domain for S3 - awsapps.com, which I took from my AWS S3 subscription. Then I had to run through a whole process of creating a new email in Azure from my existing S3 custom domain.
After the email was created I was able to purchase o365 basic license (trial version for now) and then login to Azure using a new email. o365 purchase gave me access to outlook and then recreating a new daemon application from the quickstart with the new credentials just worked.
I don't know if it makes sense what I had done as it sounds awfully convoluted. But it seems to work in the end.

How to Authenticate WPF Application with AAD B2C to gain access to Azure App Service

I'm quite stuck at the moment trying to implement authentication into a project I'm working on. The end goal of this project is to have two WPF apps and on web based app hosted on Azure. One WPF app is for an administrator, the other for staff, and lastly the web app for customers. Each application will be connected to one Azure App Service for a shared database and needs to have authentication so separate all the users. For authentication I am planning on using Azure Active Directory B2C.
I've been researching and trying to implement this for several days now on one of the WPF apps but as I stated before I'm quite stuck. From what I understand, the only way to do B2C authentication for WPF is through client managed authentication. Following the code shown on the Azure tutorial sites, other SO posts, and the Azure Git Repos, I have come up with the following code:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
authResult = await App.PublicClientApp.AcquireTokenAsync(App.ApiScopes,
GetUserByPolicy(accounts, App.PolicySignUpSignIn), UIBehavior.SelectAccount,
string.Empty, null, App.Authority);
Newtonsoft.Json.Linq.JObject payload = new Newtonsoft.Json.Linq.JObject();
payload["access_token"] = authResult.AccessToken;
MobileServiceClient msclient = new MobileServiceClient(App.AzureAppService);
MobileServiceUser user = await msclient.LoginAsync(
MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
Everything starts off great and I'm able to get my Sign-In policy to display. After logging in, I am given an IdToken and an AccessToken. After creating a JObject and adding the access token to it, I attempt to use it to login with my MobileServiceClient. But that's where I am having issues. No matter what I do, no matter what I try, I only get an exception with a 401 Error telling me I'm unauthorized. And this is the point I've been stuck at for the past few days.
Obviously I'm not doing anything special here and I imagine many people have done this before me but I just can't seem to get past this point and was hoping someone may be able to offer me some guidance. Am I way off track? Is there a better way that I could be doing this? Any suggestions or advice would be greatly appreciated as I am very new to Azure.
Thanks all!
Update:
Here's how I have my Azure Settings:
On the app service side
Client Id: "{Client Id of the AAD B2C App}"
Issuer URL: "login.microsoft.com{TennatName}.onmicrosoft.com/v2.0/.well-known/openid-configuration"
Allowed Token Audiences: "https://{App Service Name}.azurewebsites.net" (App Service URL)
On B2C side:
Web and native client enabled
Web Reply URL: "https://{AppServiceName}.azurewebsites.net/.auth/login/add/callback"
Native App: I did not know what custom redirect URL to have so I have both
"{TennatName}.onmicrosoft.com://auth/" and
"{AppServiceName}.azurewebsites.net/.auth/login/add/callback"
Update 2:
My authority is login.microsoftonline.com/tfp{tenant}/{policy}/oauth2/v2.0/authorize
And my ApiScopes = { "https://{Tenant}/thisisatest/user_impersonation" };
If the authority for the client is set to https://{your-tenant-name}.b2clogin.com/tfp/{your-tenant-name}.onmicrosoft.com/{your-policy-name}/, then the issuer URL in the app service must refer to the metadata for this authority; i.e. https://{your-tenant-name}.b2clogin.com/tfp/{your-tenant-name}.onmicrosoft.com/{your-policy-name}/v2.0/.well-known/openid-configuration.

Can someone explain HttpContext.Authentication.GetTokenAsync("access_token")

I have implemented an ASP.NET Core MVC Client using Hybrid flow, and I am wondering what the HttpContext.Authentication.GetTokenAsync("access_token") does.
If you need more background on my question:
The instructions for accessing an API from with an ASP.Net Core Client App Controller Action are generally as follows:
var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
var client = new HttpClient();
client.SetBearerToken(accessToken);
var response = await client.GetAsync("http://localhost:5001/api/stuff");
There is magic in httpContext.Authentication.GetTokenAsync("access_token") :-)
I am wondering what this function might be doing. Is it decrypting the access token from a cookie in the MVC App Domain? ... from the ID4 Domain?
I am sorry but I have been unable to find sufficient documentation on what this does or finding the cookie the access token may be in. I have looked here:
https://learn.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.authentication.authenticationtokenextensions
Does anyone know what it does? A link to more thorough documentation is a totally appreciated answer.
TU!
You can store arbitrary tokens in your authentication cookie in and that method simply returns one with a given name. Actually setting that would have happened during the sign in process. So in short, it comes from the authentication cookie for your client application and would typically be set at the point of sign in using IdSrv4.
It's a way for the client webapp to confirm separately whether the user really did authenticate with IdentityServer (the user comes to your webapp, the webapp forwards the user to IdentityServer for authentication). The id_token comes back with the user to your webapp in a browser cookie, basically when your webapp sees that id token, it does an independent check with IdentityServer, and if it represents a valid user authentication, you'll get an access token back. You can use that access token to get user claims from the userinfo endpoint.
After all of the above, you can take one of the claims and use it as a key for your application's roles/permissions.

Get Google SpreadsheetService using OAuth

I'm developing GWTP project, and below scenarios are tested successfully in my local development mode :
Get authenticated and authorized by OpenID and OAuth
Save GoogleOAuthParameters object into HttpSession.
Another action handler reuses the GoogleOAuthParameters stored in session to get SpreadsheetService object.
Use SpreadsheetService to manipulate spread sheets in GDoc.
However, when being deployed to App Engine, nothing can be read from GDoc, and no error/warning also, and returned list is always empty.
spreadsheetService = new SpreadsheetService("test");
GoogleOAuthParameters oauthParameters = (GoogleOAuthParameters)sessionProvider.get().getAttribute(HttpSessionProvider.PARAM_OAUTH_PARAMETERS);
spreadsheetService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
oauthParameters.setScope(SCOPE_SPREADSHEET);
If I clearly use username/password as below when initializing SpreadsheetService, I can retrieve data from GDoc.
SpreadsheetService sService = new SpreadsheetService("test");
sService.setUserCredentials("username", "password");
I'm using App Engine SDK 1.6.6, and gdata-spreadsheet-3.0.
Please advise whether anything I did wrongly.
Thanks!
The documentation is for .Net, not Java. If you want to develop in Java, I found a solution here: Sharing authentication/token between Android Google Client API and SpreadSheet API 3.0
String token = GoogleAuthUtil.getToken(
this,
this.accountName,
this.scopes);
SpreadsheetService service = new SpreadsheetService("my-service-name");
service.setProtocolVersion(SpreadsheetService.Versions.V3);
service.setHeader("Authorization", "Bearer " + token);
Note that this does not work for setting the token and results in a 401 for me:
// BAD CODE
service.setUserToken(token);
// BAD CODE
The documentation has complete samples in Java showing how to perform authentication with all supported mechanisms. The recommendation is to use OAuth 2.0 which is explained at:
https://developers.google.com/google-apps/spreadsheets/#performing_oauth_20

How does one avoid a cyclic redirect when writing a facebook application using pyfacebook and google app engine?

I'm trying to write my first application for Facebook using
python and pyfacebook hosted on Google App Engine. The problem I'm facing is
that of cyclic redirects. Firefox dies complaining "This page isn't
redirecting properly" when I visit http://apps.facebook.com/appname.
Here's the code:
class CanvasHandler(webapp.RequestHandler):
def get(self):
## instantiate the Facebook API wrapper with your FB App's keys
fb = facebook.Facebook(config.FACEBOOK_API_KEY, config.FACEBOOK_API_SECRET)
## check that the user is logged into FB and has added the app
## otherwise redirect to where the user can login and install
if fb.check_session(self.request) and fb.added:
pass
else:
url = fb.get_add_url()
self.response.out.write('<script language="javascript">top.location.href="' + url + '";</script>')
return
rendered_template = render_template('facebook/app.html')
self.response.out.write(rendered_template)
I see this problem when I'm logged out of Facebook. Any help is appreciated.
If you're just starting out with your Facebook app, consider using the Official Python SDK which accesses the Graph API. The REST API is being phased out.
To do authentication, use the JS SDK which will set a cookie you can read on the server side.
I agree with cope360. I've been playing around with facebook app development for a little while now. They seem to be changing their API frequently, so you'd be better off using the official libraries.
That said, to answer your question, pyfacebbok tries to get authenticaion information from information in django's HttpRequest.GET. This is out-dated, because facebook provides authenticaion info in POST data.
The source code that's responsible is in pyfacebook/facebook/__init__.py. The method name seems to be validate_request.

Resources