Extracting a Principal User in Spring Integration HTTP Inbound adapter - spring-integration

In my Spring Integration project (with Spring Security API using Basic Authorization), I am trying to access the Principal object in order to read the Username.
This is the structure of the inbound gateway:
<int-http:inbound-gateway request-channel="gatewayRequests"
reply-channel="gatewayResponses"
supported-methods="POST"
path="/api/v1/myservice"
request-payload-type="java.lang.String" reply-timeout="100">
<int-http:request-mapping consumes="application/xml" produces="application/xml"/>
<int-http:header name="principal" expression="T(org.springframework.security.core.context.SecurityContextHolder).context.authentication.principal"/>
</int-http:inbound-gateway>
I got the aforementioned expression from the reply in this:
Spring Integration and http inbound adapter, how do I extract a principal user?
Despite successful authentication, I don't see the principal - is my syntax correct in expecting the result of the expression to be mapped to a message header?
Instead of the mapping to the header, if I were to use the following, how do I access the Principal value in the code layer (assuming it gets added into the payload)?
<payload-
expression="T(org.springframework.security.core.context.SecurityContextHolder).
context.authentication.principal">
Can anyone kindly help me?
Sincerely,
Bharath

There is already a header like:
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL,
servletRequest.getUserPrincipal())
in the message sent to the gatewayRequests.
Why that doesn't work for you?
OTOH that expression must work too. If you don't have that one, then you can't assume that you are authenticated correctly...

Related

azure APIM client certificate towards SAP gateway

We're trying to use a client certificate to authenticate when calling an OData service in SAP S/4HANA. And we're calling from an azure APIM instance. As certificate we've created a self-signed certificate and configured SAP S/4HANA according to this blog (https://blogs.sap.com/2020/05/03/x.509-certificate-based-logon-to-odata-services/)
Then we test this from the browser it works like a charm.
But calling from azure APIM we get the following response from SAP S/4HANA:
<?xml version="1.0" encoding="utf-8"?> <error xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance">
<code>HTTP/404/E/Not Found</code>
<message> Service /sap/opu/odata/sap/xxxxyyyy/xxyyzz call was terminated because the corresponding service is not available.The termination occurred in system UFI with error code 404 and for the reason Not found. Please select a valid URL. If it is a valid URL, check whether service /sap/opu/odata/sap/xxxxyyyy/xxyyzz is active in transaction SICF. If you do not yet have a user ID, contact your system administrator. </message>
SAP S/4HANA support says that then calling from browser they can 'see' certificate in payload but then calling from APIM, the payload is 'empty'.
I've got the trace logs from the SAP S/4HANA gateway server and I've noticed this subtly difference calling from browser vs calling from APIM:
Browser call (successfull):
[Thr 140708195055360] HttpModGetDefRules: determined the defactions: COPY_CERT_TO_MPI (1)
APIM call (failed):
[Thr 140708197697280] HttpModGetDefRules: determined the defactions: NOTHING (0)
So the certificate is obviously reaching SAP S/4HANA gateway server but not the SAP S/4HANA Odata server. So somehow, for some reason it's lost on the SAP S/4HANA gateway server only then it comes from azure APIM.
I've tried to make the calls 100% identical (same headers same values) but I can't control the way the certificate is added in azure apim or can one ?
I read that one can set the certificate body using policy below:
<authentication-certificate body="#(context.Variables.GetValueOrDefault<byte[]>("byteCertificate"))" password="optional-certificate-password" />
but I can't figure out how to get a proper value for "byteCertificate".
Has anyone done this? Or has anyone had a similar issue?
We finally found the solution!
Thanks to microsoft APIM support team, thanks a lot :)
APIM acts like a reverse proxy and adds headers related to this role. The header "X-Forwarded-For" causes SAP to deny the request with the above misleading error message. We found a solution that SAP could configure:
ICM parameter "icm/HTTPS/accept_ccert_for_x_forwarded_for_requests" has to be set to "true" - per default it's set to "false".
(The header can't be deleted with a policy on APIM side.)

AAD B2C IEF: How to pass error code and message from REST API to the application with costom policy?

I'm using custom policy to invoke a REST API to get something from database and return in claims. It works fine but I need to extend the feature to send extra error code and error message in case any exception happens. I already returned such information as requested ("status":409, "userMessage":). But I don't know where I can get it (in HTTP header/body/somewhere else?). I understand that I can return such information in another claim. But since AAD B2C provides the status code and userMessage there must be a way to use it. Could someone please enlighten me? Thanks a lot.
enter image description here
The error message itself can’t be accessed as a claim. If you want processing to continue, then return a HTTP 200 with a JSON representing the error and use preconditions to control the journey in this case.

IIB - BIP4761E: The message flow attempted to use 'SecurityProfiles' policy

I' am trying to set LDAP Auth on Pet Store REST API in IBM App Connect v11.0.0.6 In order to do so, I have followed this guide:
Creating a security profile for LDAP
I made a BAR file out of my "pet" REST API, deployed policy to the same Integration Node, then in flow properties tried to pick my ldapPolicy but it was not present. When I enter it manually and deploy I end up with this error:
Begin running task [Deploying [pet.bar] to integration server [InteriorIntegration]]
The BAR file C:/WorkDir/workspace/pet/pet.bar has been deployed to InteriorIntegration but there were one or more failures which may mean the deployed resources will be unable to execute.
The following message was received:
BIP9339W: The values defined in the policy(s) 'ldapPolicy' in policy project 'ldapTest' match the values of the existing policy(s). Any deployed resources using the policy(s) will not be affected by the redeploy of the policy project.
BIP4761E: The message flow attempted to use 'SecurityProfiles' policy 'ldapPolicy', which has not been defined in the integration server.
BIP9320E: Message Flow 'gen.pet', 'gen.pet' encountered a failure and could not start.
BIP4761E: The message flow attempted to use 'SecurityProfiles' policy 'ldapPolicy', which has not been defined in the integration server.
BIP4761E: The message flow attempted to use 'SecurityProfiles' policy 'ldapPolicy', which has not been defined in the integration server.
BIP9320E: Message Flow 'gen.pet', 'gen.pet' encountered a failure and could not start.
BIP4761E: The message flow attempted to use 'SecurityProfiles' policy 'ldapPolicy', which has not been defined in the integration server.
BIP9333W: RestAPI 'pet' has been changed but contains errors which has prevented some resources from starting.
BIP1096E: The source 'pet.bar' has been deployed but there were one or more failures which may mean the deployed resources will be unable to execute.
The task did not complete successfully: The deployment was partially successful. Check error messages for explanation.
And here is my Policy XML:
<?xml version="1.0" encoding="UTF-8"?>
<policies>
<policy policyType="SecurityProfiles" policyName="ldapPolicy" policyTemplate="SecurityProfiles">
<authentication>LDAP</authentication>
<authenticationConfig>ldap://example.com:389/ou=example</authenticationConfig>
<mapping>NONE</mapping>
<mappingConfig></mappingConfig>
<authorization>LDAP</authorization>
<authorizationConfig>ldap://example.com:389/ou=example</authorizationConfig>
<propagation>false</propagation>
<idToPropagateToTransport>Message ID</idToPropagateToTransport>
<transportPropagationConfig></transportPropagationConfig>
<keyStore>Reserved for future use</keyStore>
<trustStore>Reserved for future use</trustStore>
<passwordValue>PLAIN</passwordValue>
<rejectBlankpassword>true</rejectBlankpassword>
</policy>
</policies>
What am I missing?
Note:
BIP9339W: The values defined in the policy(s) 'ldapPolicy' in policy project 'ldapTest' match the values of the existing policy(s). Any deployed resources using the policy(s) will not be affected by the redeploy of the policy project.
EDIT:
I think the above error occurs because ldapTest is already deployed (?). If so then why I cannot choose this policy in security profile dropdown?
Error from event logs:
( Int.Server ) The message flow attempted to use ''SecurityProfiles'' policy ''ldapPolicy'', which has not been defined in the integration server.
Policies need to be set on the integration server. Use the administrative REST API to check that a '''SecurityProfiles'' policy called ''ldapPolicy' exists.
Use the toolkit to create the required policy and deploy it to the integration server, or adjust the message flow to avoid requiring the policy.
After few days of trying to find an answer in docs and going trough trial and error I found out that to set Security Profile Name field you have to use special syntax:
{PolicyProjectName}:PolicyName
So for example if you create and deploy MyPolicies project and you want to use MyPolicy policy you have to type in Security Profile Name:
{MyPolicies}:MyPolicy

How to get User Name in SAML Assertion (OpenAM)

This is my SAML assertion from OpenAM IDP
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" NameQualifier="http://idp.ntech.com:9090/openam">/81OhgvXhHdM/+STdnPlhgkVJzDo</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="FEDE98AB33A4049999504522AB01C664219893A2" NotOnOrAfter="2012-10-27T10:56:22Z" Recipient="http://sp.ntech.com/SampleApp/fedletapplication.aspx" /></saml:SubjectConfirmation>
</saml:Subject>
but i need the username instead of NameId ,I am using OpenAM.Please help
Since you are using the transient NameID-Format, the NameID coming from OpenAM will contain just a random string. If you actually need any info about the user, then you either need to change the NameID-Format from transient to something else (possibly also using the NameID value mapping feature in OpenAM), or you need to send those extra attributes as part of the assertion (attributestatement). In order to do that you would need to configure Attribute mapping on the IdP.

Web service authentication issue - using openam j2ee agent 3

I am new to openAM. I am trying to use openAM (954) to secure my web service using J2EE agent 3.0. I have deployed my webservice (using CXF) on Glass fish 3.1.x.
I have created necessary configuration given in URL http://docs.oracle.com/cd/E19575-01/820-4803/ghuqg/index.html
I want to authenticate using user id and password. I am passing this information (userid/password) using SOAP header. But when I try to access my web service in browser it gives access forbidden message.
Are there any additional configurations required? Please let me know, I am not able to find any other information on this anywhere.
Following is the request we are sending. I am not sure about UsernameToken wsu:Id whether it is correct? How do we get this value from OpenAM dynamically at each time when we send the request.
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="HTTPdocs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-27777511" xmlns:wsu="HTTPdocs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>amadmin</wsse:Username>
<wsse:Password Type="HTTPdocs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Amit4001</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<demo:greetPerson>
<!--Optional:-->
<arg0>Ashish</arg0>
</demo:greetPerson>
Please help me solve this issue.
I want to authenticate using user id and password. I am passing this information (userid/password) using SOAP header. But when I try to access my web service in browser it gives access forbidden message.
I'm currently struggling to learn OpenAM as well and I think your specific problem is that you have not yet set up a policy (not a policy agent) after users have successfully authenticated.
If you haven't try the following steps:
Navigate to Access Control -> YourRealm -> Policies -> New Policy
Name: yourpolicyname
Rules (click new):
Name: URLPolicy
Resource Name: http:// your-webservice-url/*
Check allow get and post
Name: GetUrlPolicy
Resource Name: http:// your-webservice-url /* ? *
Check allow get and post
Subjects (click new)
Type = OpenAM Identity Subject
Name: UserAccess
Add users you want to be able to authenticate
You have to add in the * ? * if you have any GET parameters in your web page.
Hope that helps, I know the documentation around is terrible.
For your agent policy, in the Global tab: General section > Agent Filter Mode, remove ALL and add SSO_ONLY (leave Map Key blank and Map Value as SSO_ONLY). Note that this configuration isn't hot-swappable, so OpenAM has to be restarted to apply.
Here is a procedure for installing the agent on the server you want to protect:
http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/jee-install-guide/index/chap-glassfish.html
Here is a good procedure for configuring the agent policy centrally on the OpenAM server:
http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/admin-guide/index/chap-agents.html#create-agent-profiles
You might want to also control which URIs (webapps) to protect instead of the entire website. To do that, in the agent policy:
Application tab: Not Enforced URI Processing section > add the URI to protect, for example: /application1/*
Application tab: Not Enforced URI Processing section > check the "Invert Not Enforced URIs" checkbox so that it will actually enforce the "Not Enforced URI" values

Resources