JNDI Authentciation fails in plain java class but passes in Spring - java

This might sound silly but I am encountering this behavior. I am using JNDI for LDAP authentication. I have a demo program setup, where the authentication fails upon providing incorrect credentials, but the same seems to go through in a Spring controller method(I'm making a post call from a react app).
Plain Java implementation
import java.util.Properties;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class Demo {
public static void main(String[] args) {
Properties environment = new Properties();
String userDomain = "#region.company.net";
environment.setProperty(DirContext.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.setProperty(DirContext.PROVIDER_URL, "ldap://region.company.net:3268");
environment.setProperty(DirContext.SECURITY_AUTHENTICATION, "simple");
environment.setProperty(DirContext.SECURITY_PRINCIPAL, "userId"+userDomain);
environment.setProperty(DirContext.SECURITY_CREDENTIALS, "wrongPassword");
try {
DirContext context = new InitialDirContext(environment);
System.out.println("Authentication Successful !!!\n\n");
} catch (NamingException e) {
System.out.println("Authentication Failed !!!\n\n");
e.printStackTrace();
}
}
}
Controller implementation
#PostMapping("/authenticateUser")
public String authenticateUser(#RequestBody HashMap<String, String> user) {
Properties environment = new Properties();
String userDomain = "#region.company.net";
environment.setProperty(DirContext.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.setProperty(DirContext.PROVIDER_URL, "ldap://region.company.net:3268");
environment.setProperty(DirContext.SECURITY_AUTHENTICATION, "simple");
// environment.setProperty(DirContext.SECURITY_PRINCIPAL, "userId"+userDomain);
environment.setProperty(DirContext.SECURITY_CREDENTIALS, "wrongPassword");
try {
DirContext context = new InitialDirContext(environment);
System.out.println("Authentication Successful !!!\n\n");
} catch (NamingException e) {
System.out.println("Authentication Failed !!!\n\n");
e.printStackTrace();
}
return "Method executed successfully";
}
After providing incorrect password, if I execute this code then it prints Authentication Failed !!! which is expected, but when I insert this same code in a controller's method, it prints Authentication Successful !!!.
Shouldn't both behave in the same way? I find this behavior pretty weird. Perhaps, I am overlooking something?
EDIT 1 : START
It appears the line that sets the SECURITY_PRINCIPAL was commented out in case of the Spring Controller. I have commented out that part of code.
This now gives rise to another question as to why it never threw any exception ?
Not sure if I should ask this in a separate post.
Is it a proper way to authenticate by passing Username(like abc#xyz.com) as SECURRITY_PRINCIPAL or one should pass the entry path ?
EDIT 1 : END

Related

Trouble connecting sam local api to secrets manager

I'm trying to set up AWS SAM locally so I don't have to deploy every time I make a code change. But I'm having trouble getting the secrets out of Secrets Manager. I've created a new SAM project using sam init --runtime java
I then created a new secret in Secret Manager, and changed the code in the HelloWorldFunction to try to retrieve the secret.
package helloworld;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.*;
/**
* Handler for requests to Lambda function.
*/
public class App implements RequestHandler<Object, Object> {
public Object handleRequest(final Object input, final Context context) {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("X-Custom-Header", "application/json");
try {
String secretName = "testsecret";
String region = "us-west-2";
// Create a Secrets Manager client
AWSSecretsManager client = AWSSecretsManagerClientBuilder.standard()
.withRegion(region)
.build();
String secret, decodedBinarySecret;
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest()
.withSecretId(secretName);
GetSecretValueResult getSecretValueResult = null;
try {
getSecretValueResult = client.getSecretValue(getSecretValueRequest);
} catch (DecryptionFailureException e) {
// Secrets Manager can't decrypt the protected secret text using the provided KMS key.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (InternalServiceErrorException e) {
// An error occurred on the server side.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (InvalidParameterException e) {
// You provided an invalid value for a parameter.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (InvalidRequestException e) {
// You provided a parameter value that is not valid for the current state of the resource.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (ResourceNotFoundException e) {
System.out.println(e.getMessage());
StringWriter outError = new StringWriter();
e.printStackTrace(new PrintWriter(outError));
System.out.println(outError.toString());
// We can't find the resource that you asked for.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
}
// Decrypts secret using the associated KMS CMK.
// Depending on whether the secret is a string or binary, one of these fields will be populated.
if (getSecretValueResult.getSecretString() != null) {
secret = getSecretValueResult.getSecretString();
return new GatewayResponse(secret, headers, 200);
}
else {
decodedBinarySecret = new String(Base64.getDecoder().decode(getSecretValueResult.getSecretBinary()).array());
return new GatewayResponse(decodedBinarySecret, headers, 200);
}
} catch (Exception e) {
return new GatewayResponse("{}", headers, 500);
}
}
}
When I run sam local start-api and navigate to http://127.0.0.1:3000/hello, I get this error:
Secrets Manager can’t find the specified secret. (Service: AWSSecretsManager; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: 6881467f-d968-4f4e-ae60-7e3128124cc5)
com.amazonaws.services.secretsmanager.model.ResourceNotFoundException: Secrets Manager can’t find the specified secret. (Service: AWSSecretsManager; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: 6881467f-d968-4f4e-ae60-7e3128124cc5)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1632)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1304)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1058)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:743)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:717)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667)
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513)
at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.doInvoke(AWSSecretsManagerClient.java:2024)
at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.invoke(AWSSecretsManagerClient.java:2000)
at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.executeGetSecretValue(AWSSecretsManagerClient.java:878)
at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.getSecretValue(AWSSecretsManagerClient.java:853)
at helloworld.App.handleRequest(App.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at lambdainternal.EventHandlerLoader$PojoMethodRequestHandler.handleRequest(EventHandlerLoader.java:259)
at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178)
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)
But, it's the same code to get the secret that was given in the secrets manager. Is it not possible to connect to real AWS services from sam local? I had a similar issue with DynamoDB, but was able to get it working with by using DynamoDB Local.
Any suggestions on how to either connect to the real secrets manager or to fake it locally somehow?
When you run DynamoDB Local, it is actually running a mock DDB server in a thread (or as a local process depending on how you start it) within you running test process. Unfortunately, Secrets Manager and other AWS services do not offer an equivalent testing solution.
However, if you are getting back ResourceNotFoundException it seems likely that you were able to successfully connect to Secrets Manager. It may be possible that the connection to secrets manager is using a different account than the one in which you stored the secret. One way you can check which credentials the code is using is to use the STS get caller identity call.

how to authorize an user using jGit

I'm creating an application in Java and using jGit. As part of this I need to authenticate an user. I want to output if the user is existing or not. Currently I get an exception as user is not authorized. Below is my code.
import java.io.File;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
public class AuthenticateanUser {
public static void main(String[] args) throws Exception {
final String REMOTE_URL = "https://myRepo.git";
// prepare a new folder for the cloned repository
File localPath = File.createTempFile("TestGitRepository", "");
localPath.delete();
// then clone
try (Git result = Git.cloneRepository().setURI(REMOTE_URL)
.setCredentialsProvider(new UsernamePasswordCredentialsProvider("myId", "myPwd"))
.setDirectory(localPath).call()) {
System.out.println("Having repository: " + result.status());
}
}
}
when I run my above code, If I give correct credentials, I get the output as
Having repository:XXXXX
if I give wrong credentials I get error as
Exception in thread "main" org.eclipse.jgit.api.errors.TransportException: https://myRepo.git: not authorized
Instead of this I want to print, Invalid credentials.
please let me know where am I going wrong and how can I fix this.
Thanks
You go:
try (Git result = Git.cloneRepository().setURI(REMOTE_URL) {
...
} catch (TransportException te) {
System.out.println("Invalid credentials");
}
for example.
You should not tell the user if the account exists or not. As in: if you tell that an attacker, he can conclude that he already got a valid username.

Freemarker templates unable to gain access to images - Java Spring Boot

I am trying to gain access for images on an email template. I've tried following this guide.
Spring: refering the resources/static folder and this Spring 4 - addResourceHandlers not resolving the static resources
I am storing the templates in this location
my-project\complete\src\main\resources\templates
http://localhost:8080/static/templates/forgotemail/images/bottompodmiddleb.jpg
^ I want to gain access to this image -- I have a reactjs build and I am unsure if the reactjs routing is interfering with this.
I have access to this image for example.
http://localhost:8080/static/media/-bach.4f9c4b25.jpg
I create a configuration class -but I am unsure if I need to invoke it or what.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
//#Configuration
#ComponentScan("Application")
public class Configuration extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// I tried these many combinations separately.
ResourceHandlerRegistration resourceRegistration = registry
.addResourceHandler("resources/**");
resourceRegistration.addResourceLocations("/resources/**");
registry.addResourceHandler("/templates/**").addResourceLocations("/templates/**");
//registry.addResourceHandler("/img/**").addResourceLocations("/img/**");
//registry.addResourceHandler("/js/**").addResourceLocations("/js/**");
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:/resources/");
// do the classpath works with the directory under webapp?
}
}
here is the code that launches the email. "fmConfiguration.getTemplate("email-template.html")" appears to get access to the html email.
public void sendEmail(JSONObject model, JavaMailSender mailSender, Configuration fmConfiguration) throws Exception{
System.out.println("type>>>"+model);
System.out.println("mailSender"+ mailSender);
if(mailSender != null){
try {
MimeMessage mimeMessage = mailSender.createMimeMessage();
System.out.println("mimeMessage >>>"+ mimeMessage);
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setSubject("Hi");
mimeMessageHelper.setFrom("test2#gmail.com");
mimeMessageHelper.setTo("test#gmail.com");
//Map < String, Object > model = new HashMap < String, Object > ();
model.put("firstName", "Yashwant");
model.put("lastName", "Chavan");
model.put("imgPath", "resources/static/images/");
mimeMessageHelper.setText(geContentFromTemplate(fmConfiguration, model), true);
mailSender.send(mimeMessageHelper.getMimeMessage());
} catch (MessagingException e) {
System.out.println("ERROR - mimeMessage>>>");
e.printStackTrace();
}
}
}
public String geContentFromTemplate(Configuration fmConfiguration, Map < String, Object > model) {
StringBuffer content = new StringBuffer();
try {
content.append(FreeMarkerTemplateUtils
.processTemplateIntoString(fmConfiguration.getTemplate("email-template.html"), model));
} catch (Exception e) {
e.printStackTrace();
}
return content.toString();
}
I also had same kind of issue of not able to insert the images into the freemarker template.
I followed the example mentioned here
Now able to add the images with this approach.

getting error while implement connection pooling through jdbc using oracle databse

While working on some code I got followinh error,The code and the error is as given below,Tell me if further explanations required.. ............
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.directory.*;
public class OracleDataSourceRegisterJNDI {
public static void main(String[] args) {
try {
// Set up data source reference data for naming context:
// ----------------------------------------------------
// Create a class instance that implements the interface
// ConnectionPoolDataSource
OracleDataSource ds = new OracleDataSource();
ds.setDescription(
"Oracle on Sparky - Oracle Data Source");
ds.setServerName("sparky");
ds.setPortNumber(1521);
ds.setUser("scott");
ds.setPassword("test");
// Set up environment for creating initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:c:\\JDBCDataSource");
Context ctx = new InitialContext(env);
// Register the data source to JNDI naming service
ctx.bind("jdbc/ConnectSparkyOracle", ds);
} catch (Exception e) {
System.out.println(e);
return;
}
}
}
i want to use connection pooling using oracle database i am getting following error please help me out.
>
ERROR:;
javax.naming.NoInitialContextException: Cannot instantiate class: com.sun.jndi.fscontext.RefFSContextFactory [Root exception is java.lang.ClassNotFoundException: com.sun.jndi.fscontext.RefFSContextFactory]
Not sure about the code. But this is a classpath issue, you are missing the required jar from classpath. Refer: http://www.findjar.com/class/com/sun/jndi/fscontext/RefFSContextFactory.html

Fatal Exception re WAS AdminClient

I'm attempting to monitor a Websphere 7 ennvironment using MBeans, but running into numerous problems. First, I receive the following exception when using the code posted below:
com.ibm.websphere.management.exception.ConnectorException: Could not
create RMI Connector to connect to host localhost at port 2809
Here is the code generating the exception:
import java.util.Properties;
import com.ibm.websphere.management.AdminClient;
import com.ibm.websphere.management.AdminClientFactory;
public class JustAdminClient {
private AdminClient adminClient;
private void initialize() throws Exception {
try {
// Initialize the AdminClient.
Properties adminProps = new Properties();
adminProps.setProperty("type", AdminClient.CONNECTOR_TYPE_RMI);
adminProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "false");
adminProps.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
adminProps.setProperty(AdminClient.CONNECTOR_PORT, "2809");
adminClient = AdminClientFactory.createAdminClient(adminProps);
} catch (Exception ex) {
ex.printStackTrace(System.out);
throw ex;
}
} // end method
/**
* #param args
*/
public static void main(String[] args) {
JustAdminClient adClient = new JustAdminClient();
try {
adClient.initialize();
} catch (Exception e) {
e.printStackTrace();
}
} // end main
} // end class
Second, I'm running WAS standalone with security disabled. Do I need to configure any self-signed certs?
My security.xml shows:
<security:Security xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:orb.securityprotocol="http://www.ibm.com/websphere/appserver/schemas/5.0/orb.securityprotocol.xmi"
xmlns:security="http://www.ibm.com/websphere/appserver/schemas/5.0/security.xmi" xmi:id="Security_1"
useLocalSecurityServer="true" useDomainQualifiedUserNames="false"
issuePermissionWarning="true" activeProtocol="BOTH"
enforceJava2Security="false" enforceFineGrainedJCASecurity="false"
appEnabled="true" dynamicallyUpdateSSLConfig="true"
allowBasicAuth="true" activeAuthMechanism="LTPA_1"
activeUserRegistry="LocalOSUserRegistry" enabled="false" cacheTimeout="600"
defaultSSLSettings="SSLConfig_RXCW510MONNode01_1" adminPreferredAuthMech="RSAToken_1">
per the link: http://www-01.ibm.com/support/docview.wss?uid=swg21295051
Note, I can contact port 2809 two ways, via WSadamin and a Java prog containing the following:
private void connect(String host,String port) throws Exception
{
String jndiPath="/WsnAdminNameService#JMXConnector";
JMXServiceURL url = new JMXServiceURL("service:jmx:iiop://"+host+"/jndi/corbaname:iiop:"+host+":"+port+jndiPath);
System.out.println("URL = " + url);
//JMXServiceURL url = new JMXServiceURL("service:jmx:iiop://192.168.0.175:9100/jndi/JMXConnector");
Hashtable h = new Hashtable();
//Specify the user ID and password for the server if security is enabled on server.
//Establish the JMX connection.
System.out.println("Before JMXConnector");
JMXConnector jmxc = JMXConnectorFactory.connect(url, h);
//Get the MBean server connection instance.
System.out.println("Before getMBeanServerConnection");
mbsc = jmxc.getMBeanServerConnection();
System.out.println("Connected to Application Server");
} // end method
Any ideas? I'm lost and apologize for the long thread, but better to see the info upfront.
Resolved my problem using the follwoing example code snippet and notations. Note, pay particular attention to thrown exception and messages re: mssing classes; i.e. focusing on the message "could not create" message may mislead you
requires the following jar files:
%WAS_HOME%\runtimes\com.ibm.jaxws.thinclient_7.0.0.jar
%WAS_HOME%\plugins\com.ibm.ws.runtime.jar
%WAS_HOME%\plugins\deploytool\itp\com.ibm.websphere.v7_7.0.0.v20080817\wasJars\com.ibm.ws.admin.core.jar
%WAS_HOME%\runtimes\com.ibm.ws.admin.client_7.0.0.jar requires
CONNECTOR_TYPE_SOAP. CONNECTOR_TYPE_RMI fails to connect; maybe a jar issue based on the stack trace messages
public class JMXAdminClientSimple {
`private AdminClient adminClient;
private ObjectName nodeagent = null;
public void initialize() throws Exception {
try {
// Initialize the AdminClient.
Properties props = new Properties();
props.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
props.setProperty(AdminClient.CONNECTOR_PORT, "8880");
props.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
props.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "false");
props.setProperty(AdminClient.USERNAME, "");
props.setProperty(AdminClient.PASSWORD, "");
adminClient = AdminClientFactory.createAdminClient(props);
} catch (Exception ex) {
ex.printStackTrace(System.out);
throw ex;
}
}`
To use the AdminClient API with security disabled on a Sun/Oracle JRE, you need the following JARs in the classpath:
runtimes/com.ibm.ws.admin.client_7.0.0.jar
runtimes/com.ibm.ws.ejb.thinclient_7.0.0.jar
runtimes/com.ibm.ws.orb_7.0.0.jar
With these JARs, RMI should also work.

Categories

Resources