OpenAM as IDP does not redirect back to SP - authentication

I got a problem with OpenAM. Need your help.
I installed OpenAM and simply configured it as an IDP - set name and circle of trust. Then I added a remote SP by uploading SP metadata, see below
<?xml version="1.0" encoding="UTF-8"?>
<EntitiesDescriptor Name="urn:mace:shibboleth:testshib:two" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" mlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EntityDescriptor entityID="http://192.168.0.6:8080/employee/">
<SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext">
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
</NameIDFormat>
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://192.168.0.6:8080/employee/" index="1" isDefault="true" />
</SPSSODescriptor>
</EntityDescriptor>
</EntitiesDescriptor>
SP and IDP are in the same Circle of Trust.
When I do SAML request for auth from SP to IDP, I get to login page of OpenAM with SAMLRequest=... as URL params. Decoded SAMLRequest is below
<samlp:AuthnRequest AssertionConsumerServiceURL="http://192.168.0.6:8080/employee/"
Destination="http://192.168.0.7:8181/openam/" ForceAuthn="false"
ID="ID_479ff8a2-8dc5-44b5-997f-0438a2d87417" IsPassive="false"
IssueInstant="2015-01-07T13:31:01.067Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Version="2.0">
<saml:Issuer>http://192.168.0.6:8080/employee/</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" />
</samlp:AuthnRequest>
Then i do login and come to user profile page in OpenAM, instead of redirect to SP. Why it happens? What should I configure to enable redirect back to SP?

There are several things you could do:
Don’t use IP address when installing OpenAM, because cookies will not be saved on such addresses, so you can easily encounter weird problems like this.
If you have goto URL validation enabled (by default it'd disabled), then there were some old bugs around not handling redirect URLs correctly. Not sure which version you are using, so this may not really apply to you.
You should capture the network traffic with tools like LiveHTTPHeaders Firefox plugin or similar, so you can see how the HTTP requests go around. That should help you determine where exactly are things going wrong.

Related

Salesforce Merge API authentication using Bearer token

Im completely new to Salesforce and API's.
Im trying to make a Merge record call using SOAP API . Using Postman for the same .
I have imported the WSDL to my local , Called Login method to get the serverURL and sessionId.
Using these parameters to make subsequent merge calls .
During the login , I have used username and password to authenticate .
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<login xmlns="urn:enterprise.soap.sforce.com">
<username>username</username>
<password>password+auth_token</password>
</login>
</soap:Body>
</soap:Envelope>
and getting the below response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:enterprise.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<loginResponse>
<result>
<metadataServerUrl>https://**company_name**--dev.my.salesforce.com/services/Soap/m/54.0/00D0Q0000000QP8</metadataServerUrl>
<passwordExpired>false</passwordExpired>
<sandbox>true</sandbox>
<serverUrl>https://**company_name**--dev.my.salesforce.com/services/Soap/c/54.0/00D0Q0000000QP8/0DF0Q0000004Ct6</serverUrl>
<sessionId>**masked**</sessionId>
<userId>xxx</userId>
<userInfo>
.....
</userInfo>
</result>
</loginResponse>
</soapenv:Body>
</soapenv:Envelope>
Later im making the Merge call using the session ID returned from the above .
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com"> xmlns:sobject="urn:sobject.enterprise.soap.sforce.com">
<soap:Header>
<urn:SessionHeader>
<urn:sessionId>**masked**</urn:sessionId>
</urn:SessionHeader>
</soap:Header>
<soap:Body>
<merge xmlns="urn:enterprise.soap.sforce.com">
<request>
<masterRecord xsi:type="sobject:Account" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Id xmlns="urn:sobject.enterprise.soap.sforce.com">0010Q00001abcdefgh</Id>
</masterRecord>
<recordToMergeIds>0010Q00001ijklmnop</recordToMergeIds>
</request>
</merge>
</soap:Body>
</soap:Envelope>
and able to merge the records.
My question is - what should the body be if i donot want to use username and password but use Bearer token.
Can i call the login method without passing username and password?
You might be a victim of XY problem. You can't do it in SOAP API, will REST API be an option?
SOAP API's login call demands username and password (+ optional "security token", extra thing you add to password if you log in from untrusted IP). There are no other ways around it.
REST API has more options for logging in but it'd help if you read up about OAuth2 a bit before diving in. You call login and (similar to SOAP API) get back endpoint to use from now on and access_token. That access_token acts like SOAP APIs session id, you use it in next requests. Most of the time they should be interchangeable, access_token obtained via REST should be good to use in SOAP API calls.
If you already have session id / access token (will look like "00D...!....", first part is org id which you can see in Setup -> Company information for example) - you don't need login call. Call the SOAP API's merge directly and pass that value in <urn:sessionId>.
If you don't have session id, want to log in but without hardcoding username and password in your application... You have LOTS of options. Selecting right method is an art and it depends what are you making. A website, a mobile app? For internal users or community? Will it hold some credentials (for example if it needs sysadmin powers, working in background without human interaction) or will it show users the SF login screen and redirect back to the app? There's even "Internet of Things" stuff for pieces of equipment reporting their status to SF or logging in on device without keyboard (TV, fridge) where you initiate process there and finish on laptop or phone...
If you've never heard about OAuth2 before it's a big topic, "login with Google/Facebook/Twitter/LinkedIn" is just a piece of it. You'll be better off reading some blogs, checking out https://trailhead.salesforce.com/en/content/learn/trails/build-integrations-using-connected-apps or even studying to the Identity and Access Manager certification. Clicking through https://openidconnect.herokuapp.com/ might help too.
There's "username-password flow" which looks almost like SOAP API's login.
There's web server flow and user-agent flow for websites & mobile apps to send user to SF login screen (can be really SF, can be some single sign-on, doesn't matter) and back to the app. So your app doesn't see the password, doesn't see any credentials
There's refresh token option in some of these flows (you logged in once with another method, your app received access_token but also refresh_token. When access expires - app can use refresh_token to silently get back to the system without asking user to log in again. For 60 days for example). So you could still have initial "human authorises connection between the apps" but then it can just work in the background
There's JWT flow which you'll have hard time trying in Postman but there are examples such as this and this. You establish trust between SF and your app by uploading a certificate to Salesforce, marking user as allowed to use this method and then the app sends a special request just with username, no password needed.

How to force login per client with keycloak (¿best practice?)

We are currently implementing keycloak and we are facing an issue that we are not sure what’s the best way to solve it.
We have different webapps making use of the sso and that’s working fine. The problem we have is when we make log in using the sso in one webapp and then we do the same in a different webapp.
Initially this second webapp does not know which user is coming (and it’s not necessary to be logged in to make use of it). When clicking on “login”, it automatically logs in the user (by making a redirection to keycloak and automatically logging the already logged user in the other webapp). This second logging happens “transparently” to the user, since the redirection to keycloak is very fast and it’s not noticeable. This behaviour is not very user friendly.
The question is: Taking into account that this second webapp can’t know upfront which user is accessing the site (unless actively redirecting to keycloak), is it possible to force always the users to log in for a specific keycloak client? By this I mean actually ask the visitor for user/pw even if keycloak knows already them from other keycloak clients.
Thanks in advance!
In the mail listing from keycloak, they gave me a good solution but for version 4:
in admin console, go to Authentication
make a copy of Browser flow
in this new flow, disable or delete Cookie
go to Clients -> (your client) -> Authentication Flow Overrides, change Browser Flow to your new flow, click Save."
Use logout endpoint as a default login button action in your app and redirect uri param use for login page, where you use your specific client (of course you need proper URI encoding):
https://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=https://auth-server/auth/realms/{realm-name}/protocol/openid-connect/auth?client_id=client_id&redirect_uri=.....&other_params....
=> user will be logged out and then it will be redirected to the login page

How do I get Basic Authentication, GlassFish, REST, and a single page application to all work together with my own login form?

I'm using Glassfish 4 as a server with an AngularJS app as a client. Glassfish is exposing a REST API via JAX-RS (Jersey). I'm using Basic Authentication over an HTTPS connection. I have my own login form and am setting the Authorization header in my REST requests via JavaScript. My issue is that if I use normal web.xml based permissions (<auth-constraint> inside <security-constraint>), the responses come back with 401 with a WWW-Authenticate header (if the credentials are bad). This forces the browser to do the Basic Authentication dialog instead of my own and it appears there is no viable cross browser work around available on the browser side to stop it. So I need to somehow suppress the 401/WWW-Authenticate response.
I stopped using the web.xml based permissions, because it seems it is the Servlet level that is doing the 401 stuff. I was able to get Jersey authentication working with a filter and turning on the "RolesAllowedDynamicFeature" feature (in a matter similar to Glassfish #RolesAllowed with custom SecurityContext). That seems to work great and returns 403 for bad credentials (and thus no browser dialog). However, when I call my EJB's, they do not see the custom security context and the user I have set, so I get permission exceptions. If it matters: the EJB's are in a jar, the Jersey stuff is in a war, and both of them and bundled together in an ear. From what I can gather the only way to have the EJB's properly process credentials is to use the web.xml stuff.
I seemed to have painted myself into a corner and do not see how to make this work. Perhaps I can back out and return to using web.xml based permissions and somehow filter the servlet responses to not return 401/WWW-Authenticate? If so I could not find out how to do that. Or is there some way I can set EJB's security context? Or something else entirely? I wouldn't think using AngularJS with GlassFish and a REST API and Basic Authentication would be very unique, how does anyone do this?
Since posting this question I have found info on implementing a Servlet filter and using that to try to change the 401 response to a different status code. However, the filter never gains control if you have <auth-constraint> in your web.xml and the request is not authorized, so that did not help me. I still could not prevent the 401 responses.
But now I think I finally found the answer. I removed the <auth-constraint> tag from web.xml. I changed the Servlet filter to now extract the AUTHENTICATION_HEADER on its own and decode it (via javax.xml.bind.DatatypeConverter). Next I call HttpServletRequest.login (on the request object) with the decoded username and password. I catch the ServletException if the username/password combination is bad and use HttpServletResponse.sendError to send SC_FORBIDDEN. If I have a good login I call doFilter to continue on with processing of the request, and call HttpServletRequest.logout when it returns.
If I do this in combination with RolesAllowedDynamicFeature and annotations on the Jersey routines everything seems to work including calls to EJB's with their own security annotations.
Side note: before settling on HttpServletRequest.login I had tried to use HttpServletRequest.authenticate followed by checking the returned boolean, but when you gain control in that case the response has already been committed to be 401 and you cannot change it. I even tried passing a HttpServletResponseWrapper to authenticate to stop the commit from happening, but authenticate seems to get the response object through some other means, it seems to ignore the one you pass it (I even tried passed null and it didn't even notice).

Cannot login if requiressl is set to true

I have a live web site in IIS 7.5. I can login to my site correctly with http protocol till I add this line in Web.config:
httpCookies httpOnlyCookies="true" requireSSL="true"
All configuration for SSL is done but I cannot login anymore with both http and https although the cookie .ASPXAUTH is created.
If I set requireSSL="false", I can login normally.
Please help!
I had the same problem and as I came across this post searching for a solution I can explain what happened: your application was configure to use secure cookies and this requires the browser to issue the request over SSL. Therefore, if requireSSL attribute is set to true, you can't log in to your website with Http

wfresh parameter causing ADFS login to fail

I am using ADFS to do federated logins with a number of different RPs, including our own custom web app, Office 365 and some other third-party services. I have run into a problem where logins silently fail when the wfresh=0 is specified in the URL. It just keeps asking for my password over and over again. When I click the "Login" button, it doesn't log you in and redirect you to back to the RP, nor does it fail and give you an error message. Instead, it redirects you back to the STS login page, so it looks to the user like it's silently failing.
I found this question: wfresh not working with WS-Federation via ADFS, which seems to be on the right track. However, while I am definitely seeing issues with integrated logins, I am getting similar issues with Forms logins as well. The outward symptoms are different, but the behavior seems to be the same: If you specify wfresh=0, it sends you directly to /adfs/ls.
Is there any way to configure ADFS to treat wfresh correctly, or at least to ignore it?
Update: Cross-posted to MSDN Geneva Forums: http://social.msdn.microsoft.com/Forums/vstudio/en-US/7acbbd11-cd69-466b-8faa-f129f24fe1fe/wfresh-parameter-causing-adfs-login-to-fail
Update: Microsoft today released their hotfix for this: http://support.microsoft.com/kb/2896713. It is not a public hotfix, so you will need to contact Microsoft support to get the update.
Previous: I spoke with an Escalation Engineer in Global Escalation Services for Microsoft. The EE said they are aware of this issue, tracking impacted customers, and working on a solution. Anyone who is experiencing this same problem should contact Microsoft support and open a support case so they are notified when the solution is available. Microsoft support is tracking this issue internally under solution id number 2879919.
I am seeing the same thing as of lately. We have connections with some RPs and also use Office 365. If I leave my machine logged into portal.microsoftonline.com it will eventually show "page cannot be displayed" with the URL showing the long string and "wfresh=0" at the end.
Externally, if i leave my browser logged into the portal it will take me back to the form but never accept my new credentials. If I change the value of "wfresh=0" to "1" it allows me back in external and internal. I'm trying to review event logs to see anything but have not found any clues. still looking.
Would it be a good or bad solution (if possible) to use MS IIS URL rewrite to replace or remove wfresh=0 from the URL when hitting the IIS?
Best would of course be if the default installation of ADFS worked with wfresh=0 in the first place :-)
IIS URL Rewrite1
Update:
My problem was that only internal clients experienced the error while external clients (using the ADFS proxy servers) did not.
With URL rewrite on the internal ADFS 2.1 servers and the following URL rewrite rule in /adfs/ls/web.config works:
<rule name="wfresh0to1" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{QUERY_STRING}" pattern="(.*)wfresh=0(.*)" />
</conditions>
<action type="Rewrite" url="{R:0}?{C:1}wfresh=1{C:2}" appendQueryString="false" />
</rule>