Configuring Credentials and FileSystem
An overview on the OAuth2 security authorization protocol and its implementation with Apache CXF. Quick Background OAuth and OAuth2 protocols are two successive versions of an open protocol that allows you to protect your valuable web application resources against an unauthorized access, in a simple and standard method. Out of the box, the HttpClient doesn't do preemptive authentication. Instead, this has to be an explicit decision made by the client. First, we need to create the HttpContext – pre-populating it with an authentication cache with the right type of authentication scheme pre-selected.
Credentials can be configured using either a refresh token (associated with a user), or a client credential (analogous to a service principal).
Using Refresh Tokens
Add the following properties to the cluster’s core-site.xml
Applications must set the Client id and OAuth2 refresh token from the Azure Active Directory service associated with the client id. See Active Directory Library For Java.
Do not share client id and refresh token, it must be kept secret.
Oauth2 Authentication C# Client
Using Client Keys
Spring Security Oauth2 Client
Generating the Service Principal
- Go to the portal
- Under services in left nav, look for Azure Active Directory and click it.
- Using “App Registrations” in the menu, create “Web Application”. Remember the name you create here - that is what you will add to your ADL account as authorized user.
- Go through the wizard
- Once app is created, go to “keys” under “settings” for the app
- Select a key duration and hit save. Save the generated keys.
- Go back to the App Registrations page, and click on the “Endpoints” button at the top a. Note down the “Token Endpoint” URL
- Note down the properties you will need to auth:
- The “Application ID” of the Web App you created above
- The key you just generated above
- The token endpoint
Adding the service principal to your ADL Account
- Go to the portal again, and open your ADL account
- Select Access control (IAM)
- Add your user name you created in Step 6 above (note that it does not show up in the list, but will be found if you searched for the name)
- Add “Owner” role
Add the following properties to your core-site.xml
Using MSI (Managed Service Identity)
Azure VMs can be provisioned with “service identities” that are managed by the Identity extension within the VM. The advantage of doing this is that the credentials are managed by the extension, and do not have to be put into core-site.xml.
To use MSI, modify the VM deployment template to use the identity extension. Note the port number you specified in the template: this is the port number for the REST endpoint of the token service exposed to localhost by the identity extension in the VM. The default recommended port number is 50342 - if the recommended port number is used, then the msi.port setting below can be omitted in the configuration.
Add the following properties to your core-site.xml
When designing systems that enable secure authentication and authorization for API access, you must consider how your applications and users should authenticate themselves. In this article, we’ll compare three different ways to achieve this: API Keys, HTTP Basic Authentication, and OAuth. We’ll also highlight what the benefits and drawbacks are for each method.
Using API keys is a way to authenticate an application accessing the API, without referencing an actual user. The app adds the key to each API request, and the API can use the key to identify the application and authorize the request. The key can then be used to perform things like rate limiting, statistics, and similar actions.
How the key is sent differs between APIs. Some APIs use query parameters, some use the Authorize header, some use the body parameters, and so on. For instance, Google Cloud accepts the API key with a query parameter like this:
It’s relatively easy for clients to use API keys. Even though most providers use different methods, adding a key to the API request is quite simple.
The API key only identifies the application, not the user of the application. It’s often difficult to keep the key a secret. For server-to-server communication, it’s possible to hide the key using TLS and restrict the access to only be used in backend scenarios. However, since many other types of clients will consume the APIs, the keys are likely to leak.
HTTP Basic Auth is a simple method that creates a username and password style authentication for HTTP requests. This technique uses a header called Authorization, with a base64 encoded representation of the username and password. Depending on the use case, HTTP Basic Auth can authenticate the user of the application, or the app itself.
A request using basic authentication for the user
daniel with the password
password looks like this:
When using basic authentication for an API, this header is usually sent in every request. The credentials become more or less an API key when used as authentication for the application. Even if it represents a username and password, it’s still just a static string.
In theory, the password could be changed once in a while, but that’s usually not the case. As with the API keys, these credentials could leak to third parties. Granted, since credentials are sent in a header, they are less likely to end up in a log somewhere than using a query or path parameter, as the API key might do.
Using basic authentication for authenticating users is usually not recommended since sending the user credentials for every request would be considered bad practice. If HTTP Basic Auth is only used for a single request, it still requires the application to collect user credentials. The user has no means of knowing what the app will use them for, and the only way to revoke the access is to change the password.
Apache Httpclient Oauth2
HTTP Basic Auth is a standardized way to send credentials. The header always looks the same, and the components are easy to implement. It’s easy to use and might be a decent authentication for applications in server-to-server environments.
When a user is authenticated, the application is required to collect the password. From the user perspective, it’s not possible to know what the app does with the password. The application will gain full access to the account, and there’s no other way for the user to revoke the access than to change the password. Passwords are long-lived tokens, and if an attacker would get a hold of a password, it will likely go unnoticed. When used to authenticate the user, multi-factor authentication is not possible.
A token-based architecture relies on the fact that all services receive a token as proof that the application is allowed to call the service. The token is issued by a third party that can be trusted by both the application and service. Currently, the most popular protocol for obtaining these tokens is OAuth 2.0, specified in RFC 6749.
OAuth specifies mechanisms where an application can ask a user for access to services on behalf of the user, and receive a token as proof that the user agreed. To demonstrate how OAuth works, let’s consider the following use case.
A user Alice has an account with a service where she can report the current indoor temperature of her home. Alice also wants to give a third-party application access to read the temperature data, to be able to plot the temperatures on a graph, and cross-reference with data from other services.
The temperature service exposes an API with the temperature data, so the third party app should be able to access the data quite easily. But how do we make only Alice’s data available to the application?
Collecting the Credentials
Using Basic authentication, the application can collect Alice’s username and password for the temperature service and use those to request the service’s data. The temperature service can then verify the username and password, and return the requested data.
However, as we noted about, there are a few problems with this approach:
- The user has to trust the application with the credentials. The user has no means of knowing what the credentials are used for.
- The only way for the user to revoke the access is to change the password.
- The application is not authenticated
- The scope of access can not be controlled. The user has given away full access to the account.
- Two-factor authentication cannot be used
Historically, this has created a need for services to develop “application-specific passwords,” i.e., additional passwords for your account to be used by applications. This removes the need to give away the actual password, but it usually means giving away full access to the account. On the service provider side, you could build logic around combining application-specific passwords with API keys, which could limit access as well, but they would be entirely custom implementations.
The OAuth way
Let’s look at how we could solve this problem using an OAuth 2.0 strategy. To allow for better authentication, the temperature service must publish an Authorization Server (AS) in charge of issuing the tokens. This AS allows third party applications to register, and receive credentials for their application to be able to request access on behalf of users.
To request access, the application can then point the user’s browser to the AS with parameters like: Download pspice 9.1 student version.
This request will take the user to the AS of the temperature service, where the AS can authenticate Alice with whatever method is available. Since this happens in the browser, multiple-factors are possible, and the only one seeing the data is the temperature service and the owner of the account.
Once Alice has authenticated, the AS can ask if it’s ok to allow access for the third party. In this case, the read_temperature scope was asked for, so the AS can prompt a specific question.
When Alice accepts, the client can authenticate itself. A token is issued as proof that Alice accepted the delegated access, and it is sent back to the third party application.
Now, the third party application can call the API using the received token. The token is sent along with the request by adding it to the Authorization header with the Bearer keyword as follows:
Upon receiving the request, the service can validate the token, and see that Alice allowed the application to read the temperature listings from her account, and return the data to the application.
The issued token can be returned in two ways, either by returning a reference to the token data or returning the value of the token directly. For the reference token, the service will have to send a request to the AS to validate the token and return the data associated with it. This process is called introspection, and a sample response looks like this:
In this response, we can see that the user
alice has granted the application
third_party_graphs access to her account, with the scope of
Based on this information, the service can decide if it should allow or deny the request. The
client_id can also be used for statistics and rate-limiting of the application. Note that we only got the username of the account in the example, but since the AS does the authentication, it can also return additional claims in this response (things like account type, address, shoe-size, etc.) Claims can be anything that can allow the service to make a well informed authorization decision.
For returning the value, a token format like JSON Web Token (JWT) is usually used. This token can be signed or encrypted so that the service can verify the token by simply using the public key of the trusted AS.
Spring Oauth2 Client
We can see a clear difference here:
- Alice only gave her credentials to the trusted site.
- Multi-factor authentication can be used.
- Alice can revoke access for the app, by asking the temperature site to withdraw her consent, without changing her password
- Alice can allow the third-party app to access only certain information from her account.
- Claims about the user can be delivered to the service directly through the request. No additional lookups required.
- The flow is entirely standardized.
Since OAuth 2.0 was developed in the time of a growing API market, most of the use cases for API keys and Basic Authentication have already been considered within the protocol. It’s safe to say that it beats the competition on all accounts. For small, specific use cases, it might be ok to use API keys or Basic Authentication, but anyone building systems that plan to grow should be looking into a token-based architecture such as the Neo Security Architecture.
In the use case above, I only described the user flow, but OAuth, of course, specifies alternative flows for obtaining tokens in server-to-server environments. You can read more on those in my earlier post that explores eight types of OAuth flows and powers.