How can we protect data in VSTS from access via the API? - security

Context:
We have a VSTS account https://blahblahblah.visualtudio.com
We have configured it to block outside access by using Azure Premium conditional access and specifying the public IPs of our work network. So interactive access is blocked from clients outside the internal network.
But this does not block Personal Access Tokens (PATs). Nor do I see a setting to disable or block use of PATs. PATs can allow access to most of the data in our VSTS account via the REST API. Without a mechanism like the Azure AD Premium conditional access (whitelist), anyone in the world could access or modify our data by merely stealing a PAT. This seems like a huge security hole to me. Am I missing a control for that vulnerability?
Ideally, we would have a whitelist in VSTS instead of having to rely on Azure AD Premium. then the VSTS service would block both interactive and API calls that did not originate in our designated safe locations. But that does not exist so far as I know.
So, how can we protect our data from users out in the world who might access our account data via the API path and a stolen PAT?

You can disable Basic Authentication and Alternate Credentials, but that will also disable a few features on VSTS (like SSH Git and Git access from some tools that don't support the OAuth workflow).
Personal Access Token cannot be disabled this way unfortunately. Though you could have people limit the scope to their tokens and have them only create limited time tokens.
It's likely that in the future the integration with AAD will be tighter and will be able to check AAD Conditional Access.
Another important note: Once the user has logged on using AAD, they can take their laptop/device with them to another location. As long as the AAD authentication is still valid, they will not be blocked access from the other location. Conditional Access is checked upon login and renewal of the token in the case of VSTS as far as I know.
Right now only due diligence on the side of your users can prevent unauthorized access to your account. Have them treat their PAT the same way as they treat other important secret information. Use short duration PAT's, limit their scope to only what is needed and store them securely, in a Password vault like Lastpass or Keepass.
PS: in a cloud world where machines regularly get new IP addresses assigned and where IPv6 will make it harder to single out groups of machines, pure IP restrictions are not the way to keep your data safe. IP is also one of the things that is relatively easily spoofed or hidden.

Related

How does an Azure Active Directory app registration establish trust?

The Microsoft docs state:
Registering your application establishes a trust relationship between your app and the Microsoft identity platform. The trust is unidirectional: your app trusts the Microsoft identity platform, and not the other way around.
What exactly is meant by "trust" here and how does the app registration establish said trust?
The way I understand it the registration basically makes the app known to the AD, but how does that make the AD, the app is redirecting to for interactive logins, more trust-worthy to the app? Couldn't a malicious AD just pretend to know any app that's using it for logins? Wouldn't it need some kind of shared secret to assure the app that the AD really is the AD? And isn't HTTPS establishing that trust already?
It makes more sense to me the other way around: the AD receives a login request along with a redirect URI set by the app. But if the redirect URI is not known to the AD then the request is not trust-worthy and will be rejected.
I'm probably misunderstanding something, so could someone please explain the idea behind this?
In authentication world trust is a complicated word. In my opinion, the easiest way to approach this thing is taking the Google Sign-In -button as an example. You can use it to log in with your Google account on almost every website out there. Does this mean Google trusts every website out there using it? No, of course not. Do those websites trust Google? Sure they do, they have no visibility if Google returns the correct information about the users to them.
The case is very similar here as in most cases you will be using the same protocol to implement it (OAuth2 OIDC).
You are correct, you need to configure secrets & returnUrls to make sure that the App Registration is not used for malicious purposes, however, this does not create trust between the identity provider and the application. It's just technical measures to protect the client.
However, you can of course trust the application if you want to. The most common way is to grant it access to scopes so the application can do actions on behalf of the user. Usually this is done by those consent screens you probably know ("grant access to your email and phone number"). In enterprise setting, they are often omitted and access is granted with admin constent.
TL;DR; There is no inherit trust just because there is an App Registration, however you can trust an app to access user data.

Centralized identity management with different providers

I am going to build a web application that allows users to sign in with their Google or Twitter account. I think OpenID Connect(OAuth2) is the standard today to verify the identity.
I also want to provide several API services that can be only accessed with a valid access token from either Google or Twitter.
For example, all the four API's above are going to be public and so I have to protect from unauthorized users. For NodeJS based API services I can use http://www.passportjs.org/ to protect all APIs.
Assume, in the future the number of API's will be grow for example up to 20 API's and sign in with Facebook account will be also allowed.
Again, all the API's have to be protected and I have to do it 16 times with http://www.passportjs.org/.
In addition add the new provider Facebook, I have to do the changes on all 20 APIs.
The question is, is their a way to keep centralized, which means in the future when I will provide more the providers for example GITHUB for sign in I would like to do changes in one place not in 20 places.
Is the tool https://www.ory.sh/hydra what I need?
These are perhaps the two primary features of OAuth 2.0 and Open ID Connect:
Federated sign in to your UIs via multiple identity providers and the ability to easily add new options such as GitHub in a centralised manner
Full control over claims included in access tokens, so that your APIs can authorize requests however you'd like
FOREIGN ACCESS TOKENS
You should aim to avoid ever using these in your apps. Your UIs and APIs should only use tokens issued by your own Authorization Server (Ory Hydra), which manages the connection to the Identity Provider. Adding a new sign in method will then just involve centralised configuration changes, with zero code changes in either UIs or APIs.
IF YOU DON'T HAVE AN AUTHORIZATION SERVER YET
Maybe have a look at the Curity Identity Server and its free community edition - use sign in with GitHub, which has strong support for both of these areas:
Many Authenticators
Many Options for Issuing Claims
EXTERNAL RESOURCES
One exception to the above is that your APIs may occasionally need to access a user's Google resources after login, by calling Google APIs. This would require the token issued by Google. It can be managed via an embedded token approach - though it doesn't sounds like you need that right now.

OAuth2 - Can a trusted Client access User resources with Client Credentials flow

Looking at this explanation of the client credentials grant type from the OAuth website:
The Client Credentials grant type is used by clients to obtain an access token outside of the context of a user.
This is typically used by clients to access resources about themselves rather than to access a user's resources.
In case the client is a trusted app (internally developed), is it ok for it to access users' resources?
Technically, the app isn't the "resource owner" of these resources, but because it's a "super" app, developed internally, it should be able to access them, for the sake of implementing the organization's business requirements.
For example - think of your user in Google. The Google maps app creates resources owned by you (e.g places you "saved" on the map). Then, some Google daemon app with "super" permissions, can access those resources you created, in order to process them and show you relevant ads.
Does that make sense?
Thanks!
Simon.
Yes, that’s a fairly typically scenario in my opinion.
There are a few additional best practices to consider for your trusted client like storing secrets in a key vault, rotating the secret on a schedule, limiting and logging administrator access, etc.

Multi Instance Apps and Azure Authentication Best Practices

We have a multi-instance Saas Application:
Each of our clients is given their own instance and their own subdomain for the site.
Our application (Web app & API) is protected by Azure, currently with the ADAL javascript libraries
We also have a second API for system-level integration that needs to be protected, currently using a second 'native' azure app, but this is likely incorrect and we want to consolidate
Our application reads and writes to the Azure AD both through the AzureAD Graph API and Microsoft Graph API (including password reset calls)
We're looking at Azure AD application configuration options and want to make sure we're building the most sensible and secure Azure AD Application. Here are some of the documentation we've been looking at:
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-client-creds
https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-compare
We want the application to be multi-tenant to ease configuration, and allow availability in the Gallery; but when looking into doing so we're left with some security questions.
A. Which application version to use
1) v1. Allows access to both Graph API. And as suggested by Microsoft we should use this when we're not concerned with Microsoft Accounts.
2) v2. When looking at the MS Graph API documentation it recommends using v2. Reportedly doesn't work for AzureAD Graph API? Allows the same app to be of multiple types (Web App/API and native), which we may or may not need to protect both our web api and our system api (which we're still trying to model).
B. How to manage the reply URL when our clients have different sub-domains?
I've noted the following options:
1) On the app registry, we add the reply urls for all of our customers. This seems okay because we only need to do it once, but feels odd. Is there a limit to the number of reply urls?
2) Have one reply url, but manage an external tool to route the responses to the correct instance, leveraging the state url parameter. Microsoft seems to be suggesting that in this link: https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/authenticate I'm not sure if ADAL allows us to set the state for a return subdomain url though. Is this approach common?
3) Is it possible for each ServiceProvider instance in our client's directories to configure the reply url to their own subdomain? I feel like this would be the cleanest approach, but I don't see documentation for it. It would be nice if we could set the replyURL programmatically as well.
C. How to manage authorization to the Graph APIs (AzureAD and Microsoft Graph)
I've noted the following options:
1) Use the client credential flow, with a single application key (used for all clients). As clients subscribe they will admin consent with our app to give the application permission to their directory. Of course we'd do our best to keep that key secure. But if for some reason it was compromised this would put all of our clients at risk, not just the one instance that was compromised.
2) Same as 1, but use a certificate instead of a secret key. I understand this could be a little more secure, but I don't see how it wouldn't suffer from the same issue as 1.
3) Instead of using application permissions, use delegated permissions with an admin user. This would be good, in that it inherently prevents one instance of our app from talking to the wrong directory. However changes to the administrator may interrupt service; and I think it is best audit-wise that our application is responsible for the changes it makes. (Also, do delegated permissions allow for password resetting? I know for app permissions you need to run powershell script to upgrade the application's directory role)
4) Is there some way for the service principal to generate a unique key for it's directory on creation? can this be handed back to our app programmatically? Perhaps during admin consent?
Really good questions. I'll try to answer each to the best of my knowledge, but if someone has other ideas, feel free to comment/add your own answer.
A. Which application version to use
v2 should allow you to call Azure AD Graph API. The documentation you linked shows an example of specifying Azure AD Graph scopes:
GET https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=2d4d11a2-f814-46a7-890a-274a72a7309e&scope=https%3A%2F%2Fgraph.windows.net%2Fdirectory.read%20https%3A%2F2Fgraph.windows.net%2Fdirectory.write
The main decision point if you should use v2 is: Do you need to support Microsoft accounts which are not in an Azure AD? If yes, you need to use v2. Otherwise there is no problem using v1 (well, lack of dynamic permissions).
Since you are using Azure AD Graph to modify things, I'm going to guess pure Microsoft accounts will not work for you. I would recommend sticking with v1.
v2 also has some limits: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-limitations
B. How to manage the reply URL when our clients have different sub-domains?
I could not find documentation on a limit for URLs. It could be that you can add however many you want. But I am not sure :)
If your subdomains look like this: https://customer.product.com, you can configure the reply URL as:
https://*.product.com
It will then allow any subdomain to be specified in the redirect_uri.
Though note that at the time of writing this, wildcard reply URLs are not supported in v2.
C. How to manage authorization to the Graph APIs (AzureAD and Microsoft Graph)
Using multiple keys makes no sense as they are all equal anyway :) Any of them could be used to call another tenant.
You can store the secret/certificate in an Azure Key Vault, and then use Azure AD Managed Service Identity to get it on app startup.
I would prefer using delegated permissions, but if the users of the app won't have the rights to do the things your app needs to do then that does not work.
I would just make sure it is not possible for a customer's instance to call to the APIs with another tenant id. And also make sure token caches are separated in such a way that it is not possible to get another tenant's access token (an in-memory cache on the instance would be good).

Is there anyway to restrict access to Azure blob to a single IP?

I am trying to limit access to Azure blobs. I presently can provide a link that is time restricted to 5 minutes using Shared Access Signature. However just wondering if there is any mechanism to require more security such as an IP address?
If not I assume I just have to make the client go via a web role and then check there?
Update: This is supported now! Details above on Best Answer. The rest is still of interest so left it in.
N̶o̶ ̶I̶P̶ ̶f̶i̶l̶t̶e̶r̶s̶ ̶s̶u̶p̶p̶o̶r̶t̶e̶d̶ ̶d̶i̶r̶e̶c̶t̶l̶y̶ ̶-̶ ̶o̶f̶ ̶c̶o̶u̶r̶s̶e̶ ̶y̶o̶u̶ ̶c̶a̶n̶ ̶d̶o̶ ̶t̶h̶i̶s̶ ̶i̶n̶ ̶y̶o̶u̶r̶ ̶o̶w̶n̶ ̶W̶e̶b̶ ̶R̶o̶l̶e̶ ̶a̶s̶ ̶y̶o̶u̶ ̶s̶u̶g̶g̶e̶s̶t̶.̶ But this is why you should be confident with Shared Access Tokens*:
The only way that SAS blob URL could get mass published and attacked in 5 mins is if there was malicious intent from the recipient. So whatever the method of securing it (e.g. IP restriction) you would be vulnerable because you have given an attacker access. They could just download the data and publish that instead if it was IP restricted.
The shared access token combined with the timeout really prevents brute force attacks guessing the URL or any carelessness in leaving it lying about in an unsecured location over time.
So as long as you trust the person you are sharing with and you transport it to them in a secure manner you are fine.
*in most scenarios
Looks like Azure Storage Service has a new feature (shared access signatures) which allows IP-address whitelisting.
A SAS gives you granular control over the type of access you grant to clients who have the SAS, including:
The interval over which the SAS is valid, including the start time and the expiry time.
The permissions granted by the SAS. For example, a SAS for a blob might grant read and write permissions to that blob, but not
delete permissions.
An optional IP address or range of IP addresses from which Azure Storage will accept the SAS. For example, you might specify a range
of IP addresses belonging to your organization.
The protocol over which Azure Storage will accept the SAS. You can use this optional parameter to restrict access to clients using HTTPS.
Source: MSDN
There's no additional mechanism for IP filtering. You can direct all traffic through your Web Role and filter traffic there, or use SAS (as you already suggested).

Resources