How to fetch the user's other details from AD after logging into the application using LDAP registry configured in WebSphere server. I have Java EE application, which is using the single sign on. I want to get the other details like email, office location of the user which is configured in Active Directory. How do I get that?
// Retrieves the default InitialContext for this server.
javax.naming.InitialContext ctx = new javax.naming.InitialContext();
// Retrieves the local UserRegistry object.
com.ibm.websphere.security.UserRegistry reg = (com.ibm.websphere.security.UserRegistry) ctx
.lookup("UserRegistry");
From this registry, is there chance to get it?
In WebSphere Application Server you can access User Registry information -and modify it- thorugh the Virtual Member Manager componente an its API.
There's plenty of documentation and samples on IBM Infocenter. From there, the code snippet to get the properties of an entity like a user:
DataObject root = SDOHelper.createRootDataObject();
DataObject entity = SDOHelper.createEntityDataObject(root, null, DO_PERSON_ACCOUNT);
entity.createDataObject(DO_IDENTIFIER).set(PROP_UNIQUE_NAME,
"uid=SalesManager,cn=users,dc=yourco,dc=com");
DataObject propCtrl = SDOHelper.createControlDataObject(root, null, DO_PROPERTY_CONTROL);
propCtrl.getList(PROP_PROPERTIES).add("sn");
propCtrl.getList(PROP_PROPERTIES).add("uid");
propCtrl.getList(PROP_PROPERTIES).add("cn");
propCtrl.getList(PROP_PROPERTIES).add("telephoneNumber");
propCtrl.getList(PROP_PROPERTIES).add("createTimestamp");
root = service.get(root);
To get the service instance that communicates with the registry you need first to execute the Programming Prerequisites of the API. I stringly suggest you to review the Infocenter documentation.
I wrote an article about exactly that question:
http://veithen.github.io/2012/12/13/retrieving-custom-user-attributes-from.html
Note that the conclusion is compatible with what Carlos wrote: you have to use VMM.
Related
I am writing application that need to read mailbox using IMAP, but as daemon, without user interaction. I need to use OAuth2 to get access.
Because I need it without user interaction, I need to use client credentials flow. This was added this June.
I have done everything from official documentation. Registered application, added permissions, added mailbox permission using PowerShell.
When I get request access token with scope https://outlook.office365.com/.default, the one that I receive has role IMAP.AccessAsApp, so I believe that is correct. I used https://jwt.ms/ to parse JWT.
The problem is when I try to authenticate using this access token in Java, for example
Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
props.put("mail.debug", "true");
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
store.connect("outlook.office365.com", 993, "testing#mydomain.com", "accessToken");
I receive AUTHENTICATE failed. I tried same code with access token received using authorization code flow, which requires user interaction. Using that access code I was able to connect to mailbox. So the code is correct.
I even tried using client id and service id instead of email address as username, but without success.
I am not sure where I made the mistake and if I am using correct username. Any help is appreciated.
I wrote same answer here, so I am coping it here.
I think I made some progress.
I read documentation few times, tried few times from the start with same error. I even have tried using client and object ids instead of email as username, in lack of better ideas.
So this is where I think I have made mistake previous times.
On the part where it is needed to register service principal, I needed to execute
New-ServicePrincipal -AppId <APPLICATION_ID> -ServiceId <OBJECT_ID> [-Organization <ORGANIZATION_ID>]
Here I have put enterprise application object id as ServiceId argument. And that is ok.
But on
Add-MailboxPermission -Identity "email address removed for privacy reasons" -User
<SERVICE_PRINCIPAL_ID> -AccessRights FullAccess
I have put my registered application object id as User argument. I also tried setting object id of enterprise application, but it did not have success.
When I executed
Get-ServicePrincipal -Organization <ORGANIZATION_ID> | fl
I did not pay attention to ServiceId property, even with documentation specifying it and saying it will be different.
Now I cleared everything and started fresh.
I have executed all the steps again, but on the step for creating new service principal I used data from enterprise application view. When I need to add mail permission, I list service principals, and then use ServiceId value from the output, as argument for user.
With that, I was able to authorise.
Thanks everyone for sharing your experience. This has proved to be a little confusing. :)
To sum everything up, to access a mailbox with IMAPS and OAuth2 (as opposed to using Graph API which is another method Microsoft recommends):
Create an Azure App Registration
Add API permission Office 365 Exchange Online - IMAP.AccessAsApp and grant admin consent
Create a service principal, which will be used to grant mailbox permissions to in Exchange Online
Connect-AzureAD
Connect-ExchangeOnline
$azapp = Get-AzureADApplication -SearchString 'App Registration Name'
$azsp = Get-AzureADServicePrincipal -SearchString $azapp.DisplayName
# GOTCHA: You need the ObjectId from 'Enterprise applications' (Get-AzureADServicePrincipal), not 'Application registrations' (Get-AzureADApplication) for ServiceId (thanks #[jamie][1])
$sp = New-ServicePrincipal -AppId $azapp.AppId -ServiceId $azsp.ObjectId -DisplayName "EXO Service Principal for $($azapp.DisplayName)"
Grant access rights to mailboxes for the service principal
$mbxs = 'mymbx1#yourdomain.tld',`
'mymbx2#yourdomain.tld',`
'mymbx3#yourdomain.tld'
$mbxs | %{ Add-MailboxPermission -Identity $_ -User $sp.ServiceId -AccessRights FullAccess } | fl *
Get-MailboxPermission $mbxs[-1] | ft -a
You can use Get-IMAPAccessToken.ps1 to test your setup
.\Get-IMAPAccessToken.ps1 -TenantID $TenantId -ClientId $ClientId -ClientSecret $ClientSecret -TargetMailbox $TargetMailbox
Other parameters you may need:
Authority: https://login.microsoftonline.com/<YourTenantId>/
Scope: https://outlook.office365.com/.default
I have a websphere portal application running very well. The current logout command is available in default theme.
I wanted to know how to logout the portal from java/spring source code? Can we call the same command method e.g. "logout" from server side java code?
I have functionality of change password. After change password, I want to logout user.
Below is the list of items which you need to try from your portlet
final PortletStateManager mgr = getPortletStateManager(request, response);
urlFactory = mgr.getURLFactory();
url = urlFactory.newURL(com.ibm.portal.state.Constants.EMPTY_COPY); //If no state from the current request to be preserved
LogoutActionAccessorFactory logoutFct = mgr.getAccessorFactory(LogoutActionAccessorFactory.class);
LogoutActionAccessorController logoutCtrl = logoutFct.newLogoutActionController(url.getState());logoutCtrl.dispose();
finalUrl = url.writeDispose(new StringWriter()).toString();
The same can be done from a Servlet also. You will see corresponding AccessorFactory and AccessorController in the portal documentation.
EDITED
PortletStateManager is obtained from PortletStateManagerService which again is obtained from PortletServiceHome using a JNDI lookup.
The right way to find out this is by going through the Java docs of Portal. Refer the interface PortletStateManagerService. The comment section clearly tells how to get it.
You can fine the Java docs of Portal here <portal-install-root>\WebSphere\PortalServer\doc\Javadoc\spi_docs
I have a simple application written in C#.
That application works on windows machine and user account logged to the Active Directory.
In that application I retrive some information from LDAP Active Directory.
In C# I do connection with LDAP in that way:
DirectoryEntry de = new DirectoryEntry("LDAP://OU=places,DC=system,DC=org");
and next I retrieve needed data (for example):
DirectorySearcher searcher = new DirectorySearcher(de);
searcher.Filter = "(telephone=111222333)";
SearchResultCollection resultCollection = searcher.FindAll();
As you see in that application I do not need log to the LDAP with username and password but only I need to put the correct path:
The constructor of DirectoryEntry looks like that:
public DirectoryEntry(
string path
)
Of course there is a constructor with username and password, but as I said I do not need to use it:
public DirectoryEntry(
string path,
string username,
string password
)
I tried to retrieve the same information in Java and I used the similar code:
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://ad.host:389");
env.put(Context.SECURITY_PRINCIPAL, "username");
env.put(Context.SECURITY_CREDENTIALS, "password");
DirContext ldap = new InitialDirContext(env);
and next I retrieve needed data (for example):
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration tel = ldap.search("OU=places,DC=system,DC=org", "(telephone=111222333)", searchControls);
But there is a one difference. As you see I need to put username and password in Java if I want to connect to that LDAP Active Directory.
If I do not put the username and password I will see the following error:
Exception in thread "main" javax.naming.NamingException:[LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1;] remaining name 'OU=places,DC=system,DC=org'
My question is if can I log to the same LDAP Active Directory from the same machine in Java without need to put username and password?
Is there an equivalent to do this in Java like in C# (without put the username and password)?
If using env.put(Context.SECURITY_AUTHENTICATION, "none"); did not work, then your AD environment may not support anonymous authentication, understandably. Anonymous authentication is disabled by default.
When you use new DirectoryEntry(...); in C#, it may seem like you are not using any credentials, but it really uses the credentials of the currently logged on user. So it's borrowing your own credentials to make the call to AD.
Java does not do that. In fact, from the brief Googling I've done just now, it seems like it's quite difficult to make it do that, if that's what you want to do.
There is a question about how to do that here: Query Active Directory in Java using a logged on user on windows
The comment there gives a couple products to look into.
But if you don't want to use any third-party products that may complicate things, you can just provide a username and password.
If you want to test anonymous authentication in C#, you can use something like this:
new DirectoryEntry(ldapPath, null, null, AuthenticationTypes.Anonymous)
I found a walk around solution to create a process and run the powershell script.
In powershell script, you can use the "System.DirectoryServices" to search without passing the username and password.
Please refer Querying Active directory
I have a simple application written in C#. That application works on windows machine and user account logged to the Active Directory.
I guess your C# application simply uses a Windows API which under the hood automagically authenticates with Kerberos ticket granting ticket of your Windows session.
If you want to do that with another programming language you have to do a LDAP SASL bind request with SASL mech GSSAPI. However your e.g. Java-based LDAP client also have to make use of the Windows credentials cache.
See also: Java Platform, Standard Edition Security Developer’s Guide
I'm trying to subscribe to an Azure service bus topic in java. To do that, I need to create a ServiceBusContract instance. In every example I found, they do it like this:
String issuer = "<obtained from portal>";
String key = "<obtained from portal>";
Configuration config =
ServiceBusConfiguration.configureWithWrapAuthentication(
“HowToSample”,
issuer,
key);
ServiceBusContract service = ServiceBusService.create(config);
from: link
However if you take a look at the javadoc, there is no configureWithWrapAuthentication method with 3 String parameters!
I'm using the 0.3.1 version jar of the azure api.
How do I create a ServiceBusContract using these new(?) configureWithWrapAuthentication methods? Or is there something I overlooked?
Here are the parameters that we included in the configuration method.
String namespace, namespace is the name of your service bus subscription, such as johndoeservicebus.
String authenticationName, authentication name is the name of the login for WRAP, typically, it is called owner.
String authenticationPassword, authentication password is the key which you can obtain from your Azure Portal.
String serviceBusRootUri, service bus root URI is the root of the service bus service, for united states, it is “.servicebus.windows.net”.
String wrapRootUri, WRAP root Uri is the root of the WRAP authentication service, in united states, it is “-sb.accesscontrol.windows.net/WRAPv0.9”.
Apprently there is an issue with the above, tried it and it no longer works. According to github there is an open issue now:
https://github.com/Azure/azure-sdk-for-java/issues/437
The team has triaged this issue and worked on it. We've also reached out to the service bus team on the change from ACS to SAS, and to our documentation team so that we have a full-stop plan for dealing with this change, as it's not just a code issue, it's a communication issue.
This fix will be in the next release of the Java SDK, based on everything I'm hearing from the team.
I am developing an Java application using Netbeans which will fetch reports from the BI server on OBIEE 10G and display it to the client using the Java application. Can anyone suggest me appropriate steps to do this and also how to begin with it.
First of all, you will fetch the report from Presentation Services and not from BI server. BI server is a database with only SELECT statement whereas Presentation Service uses this SELECT to create and format reports.
To integrate report from BI Presentation service within a other application, you can use:
the web services: http://docs.oracle.com/cd/E23943_01/bi.1111/e16364/methods.htm#i1008939
or the GO Url: http://docs.oracle.com/cd/E23943_01/bi.1111/e16364/apiwebintegrate.htm#CACCHBHC
The links goes to the same documentation (Integrator's Guide). This is written for 11g but it will also works in 10g.
Cheers
Nico
Your question is not clear; Are you trying to invoke a Java method from OBIEE?
If yes:
You can do this by creating an Agent which is linked to an Action. The Action can invoke a java method(in an EJB). By hooking the Agent to the Action, you can schedule it as a job.
While it is possible to use the webservices and the GO url to create your web app, it is a very hard way to do so. If you have a choice, use the latest JDeveloper 11g and then, use these steps to drag and drop your Answers Reports or Dashboards to the .jspx page. It's simple, can be done in minutes rather than days provided you are familiar with JDeveloper.
EDIT: If you still want to use Netbeans, here's a snippet of code to get you started. Remember to read and understand the HtmlViewService SOAP API in the OBIEE integration doc before taking it to production.
import oracle.bi.services.soap.*
SAWSessionParameters sessionParams = new SAWSessionParameters();
sessionParams.setUserAgent("Mozilla/...."); //Copy the exact agent from your Firefox menu Help > About
javax.xml.rpc.ServiceFactory factory = ServiceFactory.newInstance();
SAWSessionServiceSoap sessionService = ((SAWSessionService) factory.loadService(SAWSessionService.class)).getSAWSessionServiceSoap();
HtmlViewServiceSoap htmlService = ((HtmlViewService) factory.loadService(HtmlViewService.class)).getHtmlViewService();
AuthResult authResult = sessionService.logonex("replace_with_your_username", "replace_with_your_password", sessionParams); //You should reuse the session for multiple HTTP Requests from the same user
String sessionID = authResult.getSessionID();
StartPageParams pageParams = new StartPageParams();
pageParams.setIdsPrefix("replace_with_your_prefix");
String pageID = htmlService.startPage(pageParams, sessionID);
ReportRef report = new ReportRef();
report.setReportPath("replace_with_full_path_to_your_report");
htmlService.addReportToPage(pageID, "replace_with_your_report_name", report, null, null, null, sessionID);
String reportHTML = htmlService.getHtmlForReport(pageID, "replace_with_your_report_name", sessionID);
System.out.println(reportHTML); //Here's the report that you are looking for
htmlService.endPage(pageID, sessionID);