Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Backend Auth Handler Implementation #7

Merged
merged 9 commits into from
Dec 5, 2024

Conversation

isuruh15
Copy link
Contributor

@isuruh15 isuruh15 commented Nov 21, 2024

Purpose

Add pkjwt handler to connect external auth servers and get access token to be used as backend auth token.

Goals

To support EPIC Auth Server for APIs that are connecting to EPIC FHIR Backends

Approach

Add pkjwt mediator to connect external auth servers and get access token to be used as backend auth token.
Add Operation_Policy definitions to be used in APIs for which the PKJWT auth token flow is required

@isuruh15 isuruh15 marked this pull request as draft November 21, 2024 06:16
@isuruh15 isuruh15 changed the title initial commit Add PKJWT Backend Auth Handler Implementation Nov 29, 2024
@isuruh15 isuruh15 marked this pull request as ready for review November 29, 2024 05:27
enable = true
token_endpoint = "https://localhost:9443/oauth2/token"
client_id = "client_id"
keystore_password = "wso2carbon"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take from CarbonUtils

@isuruh15 isuruh15 changed the title Add PKJWT Backend Auth Handler Implementation Add Backend Auth Handler Implementation Dec 3, 2024
echo -e "[WARN] healthcare.backend.auth configuration already exist"
else
# code if not found
echo -e "\n[healthcare.backend.auth]\ntoken_endpoint = \"https://localhost:9443/oauth2/token\"\nclient_id = \"client_id\"\nclient_secret = \"client_secret\"\nprivate_key_alias = \"wso2carbon\"\nis_ssl_enabled = true" | tee -a "${WSO2_OH_APIM_HOME}"/repository/conf/deployment.toml >/dev/null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cannot use default key alias (wso2carbon) right>?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the use of is_ssl_enabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default alias changed in daa4bf5.

The external token request can be made with or without ssl_context, the config is to toggle that

echo -e "[WARN] healthcare.backend.auth configuration already exist"
else
# code if not found
echo -e "\n[healthcare.backend.auth]\ntoken_endpoint = \"https://localhost:9443/oauth2/token\"\nclient_id = \"client_id\"\nclient_secret = \"client_secret\"\nprivate_key_alias = \"wso2carbon\"\nis_ssl_enabled = true" | tee -a "${WSO2_OH_APIM_HOME}"/repository/conf/deployment.toml >/dev/null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments for these deployment toml entries

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in daa4bf5

@@ -418,6 +418,13 @@ policy.limit.time_unit = "min"
patient_id_uri = "http://wso2.org/claims/patientId"
patient_id_key = "patientId"

[healthcare.backend.auth]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a toml array right? in order to support multiple backends

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in b8da50d

}
PrivateKeyJWTBackendAuthenticator privateKeyJWTBackendAuthenticator;
try {
privateKeyJWTBackendAuthenticator = new PrivateKeyJWTBackendAuthenticator();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be initialized at the deployment time and use, you can implement managedlifecycle in the mediator class.

Also since there can be multiple backend authenticator registrations, all should be initialized and the correct one should be picked up by the policy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the initialization to the constructor in b8da50d

public class BackendAuthenticator extends AbstractMediator {

private static final Log log = LogFactory.getLog(BackendAuthenticator.class);
private String authType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we define the authType in the deployment toml config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated in b8da50d

String tokenEndpoint = backendAuthConfig.getAuthEndpoint();
String keyAlias = backendAuthConfig.getPrivateKeyAlias();
char[] keyStorePass = CarbonUtils.getServerConfiguration().getFirstProperty(
"Security.KeyStore.Password").toCharArray();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constants

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in b8da50d

}
accessToken = token.getAccessToken();

messageContext.setProperty(Constants.PROPERTY_ACCESS_TOKEN, accessToken);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why setting as a property?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in b8da50d

}
headersMap.put(Constants.HEADER_NAME_AUTHORIZATION, Constants.HEADER_VALUE_BEARER + accessToken);
axisMsgCtx.setProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS, headersMap);
}else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting issues

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in b8da50d

echo -e "[WARN] healthcare.backend.auth configuration already exist"
else
# code if not found
echo -e "\n[[healthcare.backend.auth]]\n# Name of the authentication method. This name must be matched with the Config Name policy attribute in the -\n# - Replace Backend Auth Token policy.\nname = \"epic_pkjwt\"\n# Authentication type. Only pkjwt is supported atm.\n\nauth_type = \"pkjwt\"\n# External Auth server's Token endpoint URL.\ntoken_endpoint = \"https://localhost:9443/oauth2/token\"\nclient_id = \"client_id\"\nprivate_key_alias = \"key_alias\"\nis_ssl_enabled = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can support client credentials as well easily right? let's add that capability too with this effort.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in 2baf7e5

@@ -418,6 +418,26 @@ policy.limit.time_unit = "min"
patient_id_uri = "http://wso2.org/claims/patientId"
patient_id_key = "patientId"

[[healthcare.backend.auth]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we comment these by default as well, since it should be configured to the actual values by the customer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 2baf7e5

token_endpoint = "https://localhost:9443/oauth2/token"
client_id = "client_id"
private_key_alias = "key_alias"
is_ssl_enabled = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the use of this "is_ssl_enabled" ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in 2baf7e5

"policyAttributes": [
{
"name": "configName",
"displayName": "Config Name",
Copy link
Contributor

@sameeragunarathne sameeragunarathne Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like -> "Backend Auth Config" ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 2baf7e5

],
"policyAttributes": [
{
"name": "configName",
Copy link
Contributor

@sameeragunarathne sameeragunarathne Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like -> "backendAuthConfig" ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 2baf7e5

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.3.3</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

versions should be handled at the root pom

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was a build error in the tests of org.wso2.healthcare.apim.clientauth.jwt module once we specify the version of commons-logging in the root level.
Hence used the latest version

<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>5.1.1</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use the versions from the root pom

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed
2baf7e5

## Configuration Model

```toml
[healthcare.backend.auth]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readme should have a table to describe the config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in
2baf7e5

*/
public interface BackendAuthHandler {

String fetchValidAccessToken(MessageContext messageContext, BackendAuthConfig config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add java docs to interface methode

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added
2baf7e5

log.error("Auth type is not defined in the message context.");
return false;
}
if (config.getAuthType().equals(Constants.POLICY_ATTR_AUTH_TYPE_PKJWT)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use switch cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed in
2baf7e5

if (headersMap.get(Constants.HEADER_NAME_AUTHORIZATION) != null) {
headersMap.remove(Constants.HEADER_NAME_AUTHORIZATION);
}
headersMap.put(Constants.HEADER_NAME_AUTHORIZATION, Constants.HEADER_VALUE_BEARER + accessToken);
Copy link
Contributor

@sameeragunarathne sameeragunarathne Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get the authentication scheme(i.e 'Basic', 'Bearer') from the authenticator itself. This way someone can write a backend basic authenticator or any other scheme as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed in
2baf7e5


package org.wso2.healthcare.apim.backendauth.tokenmgt;

public class Token {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add class comments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in
2baf7e5

import org.apache.commons.logging.LogFactory;
import org.wso2.healthcare.apim.backendauth.Constants;

public class TokenManager {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add class comments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in
2baf7e5

@@ -572,6 +579,58 @@ private ScopeMgtConfig buildScopeMgtConfig() {

}

private Map<String, BackendAuthConfig> buildBackendAuthConfig() throws OpenHealthcareException {
// BackendAuthConfig backendAuthConfig = new BackendAuthConfig();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove commented codes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in
2baf7e5

```toml
[[healthcare.backend.auth]]
name = "backend-auth"
auth_type = "pkjwt" or "client-credentials"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the possible values in the comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in
60cde3c


TOKEN_MAP.clear();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing EoF

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in
60cde3c

/**
* Get the auth header scheme. i.e. Bearer, Basic etc.
*/
String getAuthHeaderScheme();
Copy link
Contributor

@sameeragunarathne sameeragunarathne Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have default method maybe? with value "Bearer"

@@ -0,0 +1,102 @@
package org.wso2.healthcare.apim.backendauth.impl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing licence

@isuruh15 isuruh15 merged commit 59e4608 into wso2:main Dec 5, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants