Authentication with Azure Active Directory - how to accept user credentials programmatically - python

Is there any way to login via web application or web api to Azure Active Directory (with AD credentials) using my own username and password page which is hosted outside of Azure?
From my investigation it seems there is no programmatic way to send username and password to authenticate users with Azure AD (if you hosted an app outside of Azure)
Not sure if they consider this to be a security hole of some sort (i dont think it is it https is enforced?)
Seems like you can only authenticate users by going through the code grant (which means popping out of our application to sign on to an external site).
Ultimately I want to create a python flask api that can authenticate against Azure AD directly if possible.
I have done this in the past (with other auth systems) with the Oauth grant_type=password to send username and pass, but dont think this is supported in Azure AD (correct me if im wrong?)
I know grant_type=client_credentials is supported, but that seems like its service to service auth, which is not quite what im after
http://msdn.microsoft.com/en-us/library/azure/dn645543.aspx
If its not possible to have a login page hosted outside of Azure for this, is it even possible to have one inside of Azure, seems like from examples here:
http://msdn.microsoft.com/en-us/library/azure/bc8af4ff-66e7-4d5b-b3d4-c33d2c55d270#BKMK_Browser
There is no custom login page with a password field .. (only open id logins it seems)

The Resource Owner Password Credentials Grant (grant_type=password) flow is supported by Azure Active Directory. However, before using it, consider if it is truly required. As it says in the OAuth 2.0 RFC:
The resource owner password credentials (i.e., username and password) can be used directly as an authorization grant to obtain an access token. The credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g., the client is part of the device operating system or a highly privileged application), and when other authorization grant types are not available (such as an authorization code).
If you have determined that the other supported flows will definitely not work for your scenario, then also be sure to follow the second bit of advice in the RFC:
Even though this grant type requires direct client access to the resource owner credentials, the resource owner credentials are used for a single request and are exchanged for an access token. This grant type can eliminate the need for the client to store the resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.
(Emphasis added in both cases.)
There's a .NET and ADAL sample on GitHub that uses this flow, and it should be simple enough to implement in Python: https://github.com/AzureADSamples/NativeClient-Headless-DotNet
Edit: You can host your application anywhere you want, it doesn't need to be on Azure. This applies to all flows.

Related

Microsoft Graph API: Limiting MSAL Python Daemon app to individual user access

I am building a Python Daemon app to download files which are accessible to an individual O365 user via Graph API. I am trying to use ConfidentialClientApplication class in MSAL for authorization.
In my understanding - this expects “Application Permissions” (the API permission in Azure AD) and not “Delegated permissions” for which, admin has to consent Files.Read.All.
So the questions I have are:
Does this mean, my app will have access to all the files in the organization after the admin consent?
How do I limit access to a Daemon app to the files which only an individual user (my O365 user/UPN) has access to?
Should I be rather be using a different auth flow where a user consent be also part of the flow: such as on-behalf-of (or) interactive (or) username password?
Thanks!
Does this mean, my app will have access to all the files in the organization after the admin consent?
Yes, it is the downside of application permissions usually.
How do I limit access to a Daemon app to the files which only an individual user (my O365 user/UPN) has access to?
I'm pretty sure you can't limit a daemon app's OneDrive access. You can for example limit Exchange access for a daemon app.
Should I be rather be using a different auth flow where a user consent be also part of the flow: such as on-behalf-of (or) interactive (or) username password?
It would certainly allow you to limit the access to a specific user. In general I recommend that you do not use username+password (ROPC); it won't work any way if your account has e.g. MFA. The more secure approach would be that you need to initialize the daemon app once with Authorization Code flow. This gives your app a refresh token that it can then use to get an access token for the user when needed (and a new refresh token). Note it is possible for refresh tokens to expire, in which case the user needs to initialize the app again.
You can limit the Application (Admin approved) permissions to specific resources (at least for some resources - e.g. mailboxes, calendars, SharePoint sites, ...)
Using Application Access Policy
An example for using this to restrict mailbox access to one or more users is:
https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access#configure-applicationaccesspolicy
This approach isn't possible to set currently in the MSGraph Application definition. Your admin has to use Powershell to associate an Access Policy to an Application definition.
SharePoint sites restriction
For SharePoint sites, you can use the MS Graph Sites.Selected Application permission to have Admin approved access to specific SharePoint sites.
https://devblogs.microsoft.com/microsoft365dev/updates-on-controlling-app-specific-access-on-specific-sharepoint-sites-sites-selected/

API call switching to Oauth 2.0 with openid

I used to query my financial data through Power Query in Power BI. Recently I've switched to doing it through a python script running on Google Cloud functions, triggered by Cloud Scheduler. (is this the best way?) It saves a csv file to GCStorage.
The party that provides the data I'm after is switching to oAuth 2.0 using either implicit or authorization code flow. I believe this means that somewhere in this flow a browser is opened where username and password must be entered. Also I need to give a redirect uri to this party, I'm not sure how to implement this in my current setup.
Anyone have an idea? More info about the API can be found here. https://accounting.twinfield.com/webservices/documentation/#/ApiReference/Authentication/OpenIdConnect
Usually the Authorization Code flow would be the way to go in your kind of application.
You will send a authentication request to their API(redirecting the user). They will authenticate the User and redirect the user back to your application, using the redirect URI you provided.
You can get an access token or ID token from their token endpoint using the code, your client id and your client secret.

How do I access the Salesforce API when single-sign on is enabled?

I'm attempting to make SOQL queries to the Salesforce API using the Python salesforce_api and simple-salesforce modules. I had been making these requests with a client object:
client = Salesforce(username='MY_USERNAME',
password='MY_PASSWORD',
security_token='MY_SALESFORCE_SECURITY_TOKEN')
a = client.query("SELECT something FROM some_object_table WHERE some_condition")
However, my company recently restricted Salesforce sign-in through SSO only (you used to be able to login directly to Salesforce without SSO), and the funciton is throwing either:
simple_salesforce.exceptions.SalesforceAuthenticationFailed: INVALID_SSO_GATEWAY_URL: the single sign on gateway url for the org is invalid
Or:
salesforce_api.exceptions.AuthenticationMissingTokenError: Missing or invalid security-token provided.
depending on which module I use. I suspect this is because of the SSO implementation.
I've seen the docs about creating a new app through Okta, but I need to authenticate and access the API of an existing app. What is the best way to access this API with Okta IdP enabled? It there a way to have a get request to Okta return an access token for Salesforce?
Uh. It's doable but it's an art. I'll try to write it up but you should have a look at "Identity and Access Management" Salesforce certification, study guides etc. Try also asking at salesforce.stackexchange.com, might get better answers and Okta specialists.
I don't know if there's pure server-side access to Okta where you'd provide OAuth2 client, secret, username and password and it'd be silently passed to login.
If your app is a proper web application that needs human to operate - you can still make it work with SSO. You'd have to read about OAuth2 in general (you saw it on the web, all the "login with Google/Facebook/LinkedIn/Twitter/..." buttons) and then implement something like this or this. Human starts in your app, gets redirected to SF to enter username and password (you don't see password and you don't care whether he encountered normal SF login page or some SSO), on success he/she is redirected back and you receive info that'll let you obtain session id (sometimes called access token). Once you have access token you can make queries etc, it's just a matter of passing it as HTPP Authorization Bearer header (simple-salesforce docs mention session id at top of the examples).
Look, I know what I've written doesn't make much sense. Download Data Loader and try to use it. You might have to make it use custom domain on login but there is a way for it to still work, even though you have SSO enforced. Your goal would be to build similar app to how Data Loader does it. This might help a bit: https://stackoverflow.com/a/61820476/313628
If you need a true backend integration without human involved... tricky. That might be a management problem though. They should not enforce SSO on everybody. When Okta's down you're locked out of the org, no way to disable SSO. You should have a backup plan, some service account(s) that don't have SSO enforced. They might have crazy password requirements, maybe login only from office IP address, whatever. It's not a good idea to enforce SSO on everybody.
https://help.salesforce.com/articleView?id=sso_tips.htm
We recommend that you don’t enable SSO for Salesforce admins. If your
Salesforce admins are SSO users and your SSO server has an outage,
they have no way to log in to Salesforce. Make sure that Salesforce
admins can log in to Salesforce so that they can disable SSO if
problems occur.
(If you have a web app and it's embedded as Canvas in SF - there's another clean way to have the session id passed to you. Again - this works only if you have a human rather than backend integration)
If you check the profiles in SFDC and uncheck the box that requires SSO.
"is single sign-on Enabled [] Delegate username and password authentication to a corporate database instead of the salesforce.com user database. "

How to use OpenID in Django

I'm trying to use SSO in my application provided by Ping Identity and from what I could tell they support both OAuth and ODIC if specified in the scope. While I haven't found a specific client library for Ping Indentity, I did find packages like python-social-auth and django-allauth which include an OpenID connect integration. I tried both of them but unfortunately, I didn't understand the fields required to set it up.
According to the OAuth and OpenID specifications, I was looking for fields like client id, client secret, authorization and token endpoints, redirect URI, and optional claim-to-user attribute mappings. But I have no idea what handle, issued, lifetime, association type are. Can anyone explain how to get a Ping Identity SSO fully integrated with Django such that I can still use permissions on my own local API with the authenticated and authorized users?

google endpoints restrict access to mobile clients only

I have been reading a lot about this google endpoints and I have trying to something that is not quite easy to guess. After you create a google cloud endpoint server and you deploy it is open to any HTTP request (unauthenticated). In the cloud endpoint documentation (referring to using authentication) you can read about setting OAuth2.0 to authenticate users with google account but there is no documentation about restrict the endpoint service to a specific mobile app (android or ios) and discard all other HTTP requests. So the question is how to authenticate mobile apps (no users) and prevent HTTP request (unauthenticated)? I'am building my server API(enpoints) based on Python.
Thank you.
In order to restrict your Endpoint to a specific application you can use OAuth2. This is because the OAuth2 flow does user authentication and in-turn the OAuth2 flow inherently authenticates the application requesting the OAuth2 access.
These two client samples detail how to enable authenticated calls on the client side. You have to register your apps in the Developer Console at http://cloud.google.com/console/ .
https://github.com/GoogleCloudPlatform/appengine-endpoints-helloendpoints-android (Starting after the Note in the readme)
https://github.com/GoogleCloudPlatform/appengine-endpoints-helloendpoints-ios/ (Step 8 in README)
authedGreeting is the authenticated call and you would check the User object in the method's backend project for null. If empty then you can immediately throw an unauthorized exception.
https://github.com/GoogleCloudPlatform/appengine-endpoints-helloendpoints-java-maven
Specifically, optional Step 2 in the README tells Cloud Endpoints to start looking for OAuth2 tokens in the request. If the Endpoints exposed method has a User parameter. It will populate it with a user instance only if an OAuth2 token was found, was generally valid, and the token was issued to a client ID defined in the API annotation on the service class.
During the setup of your endpoints API, in clientIds list you provide your WEB_CLIENT_ID, ANDROID_CLIENT_ID, and IOS_CLIENT_ID for example. These values tell the Google App Engine that your application will respond to HTTPS requests from web browsers and Android/iOS installed applications.
When your clients first connect your server, they must obtain an OAuth 2.0 token in order to the communication be secure and that is the reason why you use the WEB_CLIENT_ID in your installed client application. This WEB_CLIENT_ID is unique to your Google Cloud app and through it your client becomes capable of obtain an access_token and a renew_token to communicate with your backend server and your server only. This is a cross-client authorization.
So, if you need only the WEB_CLIENT_ID to obtain the access_token and the renew_token, why you need the ANDROID_CLIENT_ID and IOS_CLIENT_ID? For security reasons.
The ANDROID_CLIENT_ID is linked to a RSA signature key through the SHA1 informed at backend setup. Thus your GAE app will grant (access_token, renew_token) only installed apps signed with the same key listed at your application console (and of course in your clientIds list)
Finally Android apps signed with different or not signed will not receive any access_token, being unable to establish the secure communication channel or even communicate with your server.

Categories