rack-saml Assertion Consumer Service binding - ruby-on-rails

I am using rack-saml as middleware with omniauth-shibboleth to allow my app to work as a Service Provider.
I would like to know how to set the binding for an Assertion Consumer Service (ACS) url?
Presently my ACS url binding is 'any'. However, I have searched in rack-saml and omniauth-shibboleth to find where this is being set, and have not been able to find it.
I am trying to get my app working with testshib.org in hopes of using the app with a similarly configured Identity Provider (IdP).
I have uploaded my metadata to testshib.org. I am not sure how to implement their custom shibboleth.xml file; however my app is able to redirect to their IdP login page and cookies are set by their IdP.
Hear are some errors from the testhib.org logs.
20:14:15.864 - WARN [org.opensaml.saml2.binding.AuthnResponseEndpointSelector:206] - Relying party 'https://test_shib.com' requested the response to be returned to endpoint with ACS URL 'https://test_shib.com:443/auth/shibboleth/callback' and binding 'any' however no endpoint, with that URL and using a supported binding, can be found in the relying party's metadata
20:14:15.864 - ERROR [edu.internet2.middleware.shibboleth.idp.profile.AbstractSAMLProfileHandler:447] - No return endpoint available for relying party https://test_shib.com
Any help would be greatly appreciated.

There may be a better way to do this; but I got things working by overriding Onelogin::Saml::Authrequest (and the other classes that called Onelogin::Saml::Authrequest) and then changing AssertionConsumerServiceURL to AssertionConsumerService in the create method.

in lib/rack/saml.rb you will find:
#config['assertion_consumer_service_uri'] ||= "#{saml_sp_prefix}#{#config['protected_path']}"
So, in your config/rack-saml.yml you can configure it like this (and you may need to if having the port number in the uri causes problems):
assertion_consumer_service_uri: https://www.abc.edu/users/auth/shibboleth/callback
Also, you shouldn't need anything from their shibboleth2.xml file, Just put the certificate from their provider's xml in your metadata.yml config file:
---
idp_lists:
https://idp.testshib.org/idp/shibboleth:
certificate: |-
-----BEGIN CERTIFICATE-----
MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzEV
...
8K/qhmFT2nIQi538n6rVYLeWj8Bbnl+ev0peYzxFyF5sQA==
-----END CERTIFICATE-----
saml2_http_redirect: https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO

Related

How to configure or customize REALM Metadata endpoints in Keycloak for SAML2.0

Context:
I have a keycloak inside a docker, I understand that there is a "proxy reverse" doing something like transforming this url for example: "http://example.com" into "http://171.20.2.97:8082" (this is the actual place where the Keycloak is "deployed" or "up"). It is just an example, my clients when they need to consume an endpoint from one microservice of mine do not use numbers, they use example.com.
so in the Keycloak when you want to see the metadata of the realm for SAML2.0 you can do it by following this link which is in the REALM settings section:
https://example.com/auth/realms/REALM-NAME/protocol/saml/descriptor
as you can see I am using "example.com" not "171.20.2.97:8082" to access the metadata link.
The problem is that inside the METADATA, the endpoints for SingleSignOnService, SingleLogoutService, etc. Are all configured to be "http://171.20.2.97:8082/auth/realms/REALM-NAME/protocol/saml" (notice it is using the numbers and not example.com) and this causes that when the clients that want to use SAML.
Send inside their SAML REQUEST "Destination" attribute like so: "http://example.com/auth/realms/REALM-NAME/protocol/saml" and this causes an invalid request error, with reason invalid_destination, because the request attribute Destination was expected to be:
"http://171.20.2.97:8082/auth/realms/REALM-NAME/protocol/saml" like is inside the Metadata.
So my question is, how can I edit the metadata to change the endpoints numbers to example.com or if that is not possible, how can I make example.com get translated to 171.20.2.97:8082 inside my keycloak server? Or if you know another way to solve/figure out this it is very welcome
I feel like a BEAST after finding out how to achieve what I needed after like 3 weeks of searching about keycloak and SAML (I overcame many obstacles this was the lastone), finally I managed to fix this by using the "Frontend URL" setting in my REALM settings, there I can put anything I want so that it changes "http://171.20.2.97:8082/auth/" (inside the metadata urls) for whatever I configure there, so for example if I set Frontend URL to:
https://example.com/auth/
now all my metadata endpoints will be like so:
https://example.com/auth/realms/REALM-NAME/protocol/saml
instead of:
http://171.20.2.97:8082/auth/realms/REALM-NAME/protocol/saml
now my client is being able to properly login with SAML2 using keycloak.
how did I manage to find out this? Well there is not much info so this was what gave me the hint: Keycloak behind nginx reverse proxy: SAML Integration invalid_destination
The person asking said that he configured frontend-url, and I wanted to give a try to that, and after checking if that changed metadata urls, surprise it did =)

Implementing Oauth2 from scratch

I want to implement Oauth2 protocol from scratch for study purposes.
I'm following the Github guide after having created an App with a Client ID and Client Secret.
The two information sources are pretty simple and are:
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
https://gist.github.com/technoweenie/419219
In particular, I'm starting from the first step pasting on my browser:
https://github.com/login/oauth/authorize?client_id=&redirect_uri=http://localhost:8080/auth/temp&scope=user&state=&allow_signup=true
I have a Spring application listening on port 8080 (I don't want to use Spring Security because I want to implement the protocol from scratch) with the following and working endpoint exposed:
#RequestMapping("/auth/temp")
public String redirectAuth(HttpServletRequest request) {
//TODO implement next steps
return "here we are!";
}
but when I go to the github link I get a 404 not found error, as my localhost application wouldn't exist.
I expect the official guide has some mandatory information missing, such as some other endpoints which my application must expose in order to be queried, for instance, about the client secret.
So, what am I missing?
Github only supports the auth code oauth 2 flow. It might be helpful to read up on that.
I have a blog and a video on the auth code flow that may help.
Disclaimer: I work at and created them for Ping Identity, but I think
they'll be helpful even for your study purposes.
https://developer.pingidentity.com/en/blog/posts/2019/what-are-oauth-2-0-grant-types-part-1-authorization-code-flow.html
https://youtu.be/eg7I8x-u0sc
You haven't included your client_id in the authorisation url:
https://github.com/login/oauth/authorize?client_id=&redirect_uri=http://localhost:8080/auth/temp&scope=user&state=&allow_signup=true
The authorization server (GitHub) needs this value to identify the client you have registered.

Google Assistant SDK refusing authenticated channel as "UNAUTHENTICATED"

I am trying to create a Google Assistant for my Raspberry Pi in Kotlin. I implemented a OAuth flow using the so called "device flow" proposed in this IETF draft, since my Raspberry shall later just expose a web interface and does not have any input devices or graphical interfaces.
Google does support this flow (of course) and I obtain a valid access token with user consent in the end. For testing purpose I also tried a default authorization flow that will just forward the user to localhost, as it is normally done but it did not solve the problem.
I tested the access token using this tool and it confirmed validity of scope and token. So the token itself should work.
Scope is: https://www.googleapis.com/auth/assistant-sdk-prototype as documented here
This actually does not point to any valid web resource but is referenced in every documentation.
Then I tried to stream audio data to the assistant SDK endpoint using the gRPC provided java stubs. As took a third party reference implementation as a guide how to authenticate the rpc stub. But neither the reference implementation nor my own one works. They both report
io.grpc.StatusRuntimeException: UNAUTHENTICATED: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
The stub is authenticated this way:
embeddedAssistantStub.withCallCredentials(
MoreCallCredentials.from(OAuth2Credentials
.newBuilder()
.setAccessToken(
myAccessToken,
myAccessTokenExpirationDate))
.build()))
and the authenticated request is performed like this:
val observer = authenticatedEmbeddedAssistantStub.converse(myStreamObserverImplementation)
observer.onNext(myConfigConverseRequest)
while(more audio data frames available) {
observer.onNext(myAudioFrameConverseRequest)
}
observer.onCompleted()
(I prefixed pseudo variables with "my" for clarity, they can consist of more code in the actual implementation.)
I even contacted the author of this demo implementation. He told me, last time he checked (several months ago) it was working perfectly fine. So I finally ran out of options.
Since the client implementation I took as reference used to work and I do actually authenticate the stub (although the error message suggests the opposite) Probably, either my valid access token with correct scope is not suitable chosen for the assistant API (though I followed the suggestions of google) or the API servers had a change not properly documented in the getting started articles by google.
So: Did anyone ran in the same problem and know how to fix it? I have the project on github. So if anyone needs the broken source code, I can do a temporary commit that produces the error.
Note, to save some works for mods: This issue referres to this and this question, both unresolved and using different languages but describing a similar problem.
Well, seems I was right about my second assumption: The error is server side. Here is the github issue, let's just wait for the fix.
https://github.com/googlesamples/assistant-sdk-python/issues/138

Can I communicate with my server in a way that can't be figured out and spoofed by a third party?

It seems there are a couple choices within Xcode/iOS to communicate with my server, using simple HTTP requests or creating a full blown socket system. What vulnerabilities does each have? My main concern is that I can't allow someone to replicate a call that's not from my app, like you could spoof an AJAX call by examining a webpage's Javascript and getting the address for the call. Obv it wouldn't be so simple with a phone app, but I don't know what's possible for hackers.
Use HTTPS.
Override the TLS chain validation to fail if the public key doesn't match the one stored in your app.
In Apple's TLS validation doc below, start with "Listing 3 Overriding the trust object used by an NSURLConnection object", then add code so that if certificate evaluation succeeds, you check the key inside the challenge's protection space against a known-valid key (or keys) before allowing the connection to proceed.

iOS -- Technique for securing SOAP API credentials embedded in binary

The answer proposed in Embed API credentials in iOS code is not an option for me.
My app communicates with a back-end SOAP API over HTTPS. My API credentials are sent in every request.
I don't have control over the server implementation, so I'm not able to add an intermediary authentication server and migrate to a token-based implementation.
Because I have to embed my credentials with my app's binary (I understand that this is far from ideal, on principle), i am looking for best practices to make my credentials as secure as is possible.
From what I've read, I've gathered:
Don't include credentials in an external file (such as a .plist)
Don't include credentials as simple NSString * const declarations. (Is using a char * safer?)
Don't do something obvious, like put my credentials in an Objective-C singleton called AuthenticationKeyManager
I also saw this article: http://applidium.com/en/news/securing_ios_apps_debuggers/
=> tldr: add release-mode code in the main.m to prevent the app from running if a debugger is attached
Note: I am able to implement SSL pinning.
Are there any other measures I can take to safeguard my access credentials?
There is described how create and use encrypted plist: http://aptogo.co.uk/2010/07/protecting-resources/
But aes key from it is stored in static NSString *sharedKey;

Resources