Jmeter 2.10 and oAuth authentication - oauth

Testing APIs authenticated with oAuth with the Jmeter 2.10 and stuck with making it work with oAuth headers.
I found 2 plugins for Jmeter, which suppose to do this, but there are different issues with each of them:
https://code.google.com/p/jmeter-oauth/ — throws NoSuchMethodError in the logs, and community say that it's due to incompatible versions;
http://jmeter-plugins.org/wiki/OAuthSampler/ — this one is not allowing to send oauth_token and oauth_token_secret, which is required on for my API, so authorization fails.
In order to complete request I need to send Authorization headers with 4 oAuth parts. I cannot compose the header manually because it requires signature, generated based on the token and message body.
What other approach can I try?

You can do this using JSR223 PreProcessor using Groovy language.
This component allows you to add custom Groovy code for example and generate the TOKEN variable:
You can then use the HTTP Header Manager component:

I was able to make it work by using the following approach:
Configure a keystore with client certificate and key.
Configure SSL Manager with this certificate.
Configure http request with Client Certificate and SSLManager parameters.
The client certificate is the one that contains the private key for the OAuth signature generation.

Related

Example of loopback interface redirection to read the authorized code from oauth URI

I am working on an desktop based Java Swing application on which I have to invoke the web browser for authenticate and get the authorization code from that URI.
I was going through https://www.rfc-editor.org/rfc/rfc8252 RFC and read the "loopback interface redirection" terminology. Able to find the theocratical concept around this on Net but not able to find any example code.
Can someone help me to understand this better from code perspective or link to any example?
I have some code samples you can easily run from your local PC but they are not coded in Java. Hopefully they help you to understand how the solution works though:
Desktop Sample using Loopback Server to Receive Login Response
Desktop Sample using Private URI Scheme to Receive Login Response
The Nimbus OAuth Libraries might prove useful for a Java implementation.
We have achieved this after using the RFC 7636 https://www.rfc-editor.org/rfc/rfc7636 where in Java application, we are starting the inbuilt java http server on random port.
After starting the local server, we generate one random string called code_verifier and then client change it to code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) using SHA256 and create Bas64 encoded URL string and open the browser to do the authentication.
Once authentication is done from browser, webservice creates an auth token against the JWT token and store in DB along with code_challange.
Browser pass the auth token to client and after receiving the response, then client pass the auth token along with code_verifier to get the authorization JWT token. Webserver verifies both the entries against the stored info and passed back the authorization token after successful verification.

IBM Mobile First Server OAuth with JWT Authentication - Incorrect JWT Format error

I am developing a performance test script for hybrid mobile application using Rational Performance Tester V9.0 & V8.7.
The mobile application sends the request to IBM Mobile First Server v8.0 which authenticates its user using OAuth with JWT (JSON Web Token).
I tried enhancing the script and replayed but it fails at login step in an API which requests for token /mfp/api/az/v1/token
Below mentioned is the request & response for the API call,
URI: POST /mfp/api/az/v1/token
Request:
client_assertion=eyJhbGciOiJSUzI1NiIsImp3ayI6eyJhbGciOiJSUzI1NiIsImUiOiJBUUFCIiwiZXh0Ijp0cnVlLCJrZXlfb3BzIjpbXSwia3R5IjoiUlNBIiwibiI6IjAtX19nSjFLWnZsVlU5M1JGRlFuZk80TGdLeUhTN3hIMVg3RUw2ZGhKa1B6SGQ0cUhEaHdFQzFIT0k0cHhmeEMzZWh6M1I3cXQtU3A5WnpOb3o4Z1lDTVRmSmh3T21OZWh5dkNkMDU3V09PVjB1b0ZPQmFpS21pMG9qdHJoMFMzMlNuS1VWTElwekxhQUZJSkhsOGtCSm9sZ21JQW9hZHNRdFpTUWg0MVJZN2c3aWNCUzlJRkRCdGdDbUtjRHlRY29VSnpTWkIxZk1ZY2VYNGFBNDZ3elkwRkdaY3hxcG11U1kwV0xCTEhDUjdLSm9oa2wwZDk4OFlSVGtuQkE3dFBLTEF4RnQxT2daQ1BYR1owWW41ZHFKN3ZwWXZtd21hc09vSFNacWp3cktMOW51MDR0QUZ1OENHZ3ZrTnZPUmJjRFRQaElvcy1iQ0J0ZFhXZjBWek1uUSIsImtpZCI6IjYxZWNkMjY2LTNjYTItNDhlYy04M2M2LTY3MTk5MGVjNzdlOCJ9fQ%3D%3D.eyJpc3MiOiJlQmFua2luZyR3ZWIiLCJzdWIiOiI2MWVjZDI2Ni0zY2EyLTQ4ZWMtODNjNi02NzE5OTBlYzc3ZTgiLCJleHAiOjE1Mzk3Nzc3NjMxNzQsImlhdCI6MTUzOTc3NzcwMzE3NCwianRpIjoiLTQ0NjkwNTY3Njc4NzAzMTYyNzEiLCJhdWQiOiJhei92MS90b2tlbiJ9.nMcfmOPDcLjONOXhF%2B3mArM87AiPfqEPp5Bk815f9Dg7VaaIgY41jeSmlWASCdmjf9Cno3%2BwHGom%2BzAEGQDdFkmBjLpCY7TnCAv9j8HzIPDubYdSQW2pq7WKVz%2FvEQ8Z5Pa8jh8aAMTlrsBnjlPoiVfcqHBh%2F2vpHZnKvkSoCOcA2TAeJnioSlp4vpWOc26IsMwKYMqZlVs9K2Z8JwHQvESKlzDu9etxYnnQfxyqunwhG%2B5T9GKgMmCAo1%2BBGqqsEtTwOG5UmhoyYIYbMnNHzHFdl8fWwMMOtpf%2F3RqjBYNeAsZ%2BTuGkskLlA5hrLiHmfOhzPYstr8tCO2IMLbTpjQ%3D%3D&code=5059335353176972418&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fuatirmob.qcdib.com%2Fmfp%2Fapi%2Faz%2Fv1%2Fauthorization%2Fredirect%2F17553a31-f583-44f9-9b7a-d8fab31b3bff&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
Response:
{"errorCode":"invalid_client","errorMsg":"Incorrect JWT format"}
I noticed that the client_assertion value carries dynamic data in JSON form when I decrypted with https://jwt.io/#debugger
Also, developed encryption logic mentioned in IBM mobile first site to generate the client_assertion value referring this link: https://mobilefirstplatform.ibmcloud.com/blog/2016/08/09/performance-testing-for-mobilefirst-foundation-8-0/
It was not successful after following the above steps.
Please provide solution to handle the /mfp/api/az/v1/token request and generate access token which will passed in the subsequent requests.
Thanks in advance.
We have documented performance testing instruction for JMeter.
Please refer to link here for more details - https://mobilefirstplatform.ibmcloud.com/blog/2016/08/09/performance-testing-for-mobilefirst-foundation-8-0/
Please refer to section "Sign grant code" and ensure you are following steps properly [ https://mobilefirstplatform.ibmcloud.com/blog/2016/08/09/performance-testing-for-mobilefirst-foundation-8-0/#sign-grant-code ]
Try the latest Mobilefirst v8 build (late Oct 2018) which will fix this.

Configuration of Microsoft Graph OAuth2 authentication in Spring Security - Error AADSTS90014

I am writing an SSO provider for MS Graph APIs Azure AD v2 endpoint leveraging Spring OAuth2.
I am progressing with the implementation and constant testing but I stumbled upon an error returned by AAD which is puzzling me. After all, this should all be plain standard OAuth 2 flow.
I successfully configured my application on MS dev portal, providing a localhost redirect URL (which, for the record, is the only supporting the http scheme. Kudos to MS). So when I invoke http://localhost/myapp/auth/office365 Spring security successfully intercepts the invocation, provides a correct redirect to my browser with client ID to https://login.microsoftonline.com/common/oauth2/v2.0/authorize with expected parameters.
Microsoft shows a consent screen to me, after which I get redirected back to my Spring Security application via HTTP GET with expected authorization code parameter.
The problem is that when the application tries to negotiate the given authorization code for a bearer token headaches start. Spring Security invokes a POST to https://login.microsoftonline.com/common/oauth2/v2.0/token but ends in 401 error.
Here is the stack trace
error="invalid_request", error_description="AADSTS90014: The request body must contain the following parameter: 'client_id'.
Trace ID: 9acd2a10-1cfb-443f-9c57-78d608c00c00
Correlation ID: bf063914-8926-4e8f-b102-7522d0e3b0af
Timestamp: 2017-10-09 15:51:44Z", correlation_id="bf063914-8926-4e8f-b102-7522d0e3b0af", error_codes="[90014]", timestamp="2017-10-09 15:51:44Z", trace_id="9acd2a10-1cfb-443f-9c57-78d608c00c00"
at org.springframework.security.oauth2.common.exceptions.OAuth2ExceptionJackson2Deserializer.deserialize(OAuth2ExceptionJackson2Deserializer.java:100)
at org.springframework.security.oauth2.common.exceptions.OAuth2ExceptionJackson2Deserializer.deserialize(OAuth2ExceptionJackson2Deserializer.java:33)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readInternal(AbstractJackson2HttpMessageConverter.java:215)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:193)
at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport$AccessTokenErrorHandler.handleError(OAuth2AccessTokenSupport.java:235)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:621)
at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:137)
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:209)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:148)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:121)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:105)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
I have looked into Spring security implementation to find the cause,.
It happens that the error message error="invalid_request", error_description="AADSTS90014: The request body must contain the following parameter: 'client_id'. is self explanatory: MS Graph wants the client ID (which is still supplied by the basic authentication header) in the request body. Stop for a moment. I want to use plain old Spring Security and not third-party specific jars in order not to pollute my classpath.
Looking into Java source code of Spring OAuth 2 the problem is damn clear. Spring uses the client ID only in getParametersForAuthorizeRequest, which is used to generate the redirect URL. When it comes to getParametersForTokenRequest the client ID is not specified in the form.
Question: who is right here? How do I tell Spring that MS wants the client id in the token request after an authorization code has been obtained?
Just to clarify, you're not actually authenticating with or against Microsoft Graph. You're actually authenticating against Azure Active Directory. The Microsoft Graph API accepts the bearer token you'll end up with but it doesn't issue the access token itself.
It isn't clear which endpoint you're using for the Authorization Code flow, AAD has two of them: v1 and v2. The primary difference being that v2 uses a central registration and can authenticate both work/school and personal accounts.
Regardless of the endpoint, you do need to supply the clientid in the request body when you're requesting an access token. There are actually several values you need to provide in the body. Also note that these need to be provided as application/x-www-form-urlencoded.
For the v1 endpoint you provide (line breaks for readability only):
grant_type=authorization_code
&client_id={client-id}
&code={authoization-code}
&redirect_uri={redirect-uri}
&client_secret={client-secret}
&resource={resource-uri}
The v2 endpoint is almost identical but uses scope instead of resource:
grant_type=authorization_code
&client_id={client-id}
&code={authoization-code}
&redirect_uri={redirect-uri}
&client_secret={client-secret}
&scope={scopes}
OP's edit
Now, back to Spring Security. Spring by default uses an HTTP basic authentication scheme against Azure AD. In that scheme, the client ID and secret are encoded into the HTTP Authorization header, then the form only contains the authorization code and state parameter, so here is why I (the OP, ndr) was puzzled about why AAD refused the authorization.
In order to pass client ID and secret into the form, we can tell Spring Security to use a different supported authentication scheme. The form authentication scheme will push the client ID and secret into the form.
The below code works and retrieves the access token.
<oauth2:resource
id="msAdAuthenticationSource"
client-id="${oauth.appId}"
client-secret="${oauth.appSecret}"
type="authorization_code"
authentication-scheme="form"
client-authentication-scheme="form"
use-current-uri="true"
user-authorization-uri="${oauth.authorizationUri}"
access-token-uri="${oauth.accessTokenUri}"
scope="${oauth.scopes}"
pre-established-redirect-uri="${oauth.redirectUri}" />
Please note the two
authentication-scheme="form"
client-authentication-scheme="form"
Problem solved, a lot more to come!

Google's OpenID Connect says: OAuth 2 parameters can only have a single value: client_id

As part of the OpenID Connect (OAuth2 for Login), my application is supposed to request an access token, given a one-time authorization code, via the endpoint https://www.googleapis.com/oauth2/v3/token. According to documentation, this request needs 5 parameters passed to it, client_id among them. That is exactly what my application does, using the Perl module Net::OAuth2.
Everything has been working fine for several months, but today I was notified that it stopped working. No updates were made to the application code nor the libraries used by it.
The message my application now receives from the server when calling the token endpoint is this, in a 400 error response:
OAuth 2 parameters can only have a single value: client_id
A Google search suggests nobody has ever seen this message before, or lived to tell the tale. There doesn't seem to be a general issue with Google's OpenID Connect (other services based on it are working flawlessly), and the imminent shutdown of the old login protocol doesn't seem relevant.
More testing: removing all parameters except client_id causes this error message:
Required parameter is missing: grant_type
Supplying only client_id and grant_type produces the original error message again.
Does anyone have an idea what's going on here?
Google changed this behavior few days ago, so any OAuth2 library using Basic Auth headers AND body request parameters will start to see messages like
OAuth 2 parameters can only have a single value: client_id
or
OAuth 2 parameters can only have a single value: client_secret
So, you must now do NOT use both (the Auth headers and body request parameters) at the same time to send credentials to Google.
And according RFC 6749, the preferable way to send credentials is through Auth headers (thanks #JanKrüger for alert me about this).
Got the same error. It seems the problem is that NET::OAuth2 sets the authorization header when exchanging authorization code for access token. If you remove this header everything works fine.
Check the get_access_token method in Net::OAuth2::Profile::WebServer module. The authorization header includes client_id:client_secret base64-encoded string. Apparently Google now treats this duplication as an error.
The right way of fixing this is to set the secrets_in_params parameter when creating Net::OAuth2::Profile::WebServer object. Look in the Net::OAuth2::Profile documentation for more details.

How to have a SAML request/response signed using Spring Security SAML extension

I was able to have my application act as a SP with the IDP SSOCIRCLE using the Spring Security SAML extension. My customer has the following requirements:
1. Have the assertion signed: The assertion sent from the IDP is signed and it is working fine.
2. Have the request/response signed: When using SSO Circle to generate the metadata file. I selected the option AuthnRequestsSigned to true. I uploaded my SP metadata to the SSO Circle IDP. The SP metadata had the following values as true: AuthnRequestsSigned & WantAssertionsSigned. When running the application neither my request nor the response I get are signed.
I am having issues to have the second requirement done. I am new to SAML and to Security in general. What am I missing here?
UPDATE
After taking into consideration Vladimir's comments. I changed my binding to HTTP-Post, so now I am sending the SAML Request with the signature shown.
I was able to send the request signed using my private key(not the one provided by the sample project) by doing the following:
Create a keystore, CSR, and a public key certificate using the keygen tool.
Update the Digital Signature section in my SP metadata file to have the new certificate
Remove the old SP metadata file from IDP SSOCIRCLE and add the new SP metadata file
Change spring configurations to have the JKSKeyManager to use the new keystore I created with the new alias and password.
What I need to do now is to have the IDP(SSOCIRCLE) send the response where
a. The response is signed
b. The assertion is signed
How can that be achieved? what changes do I need to do to handle that, given that
the signing of the response should be different than the signing of the assertion.
Thanks.
HTTP-Redirect binding requires that any ds:Signature element present on the SAML message itself is removed before sending of the message:
Any signature on the SAML protocol message, including the XML
element itself, MUST be removed. Note that if the content of the message
includes another signature, such as a signed SAML assertion, this
embedded signature is not removed. However, the length of such a message
after encoding essentially precludes using this mechanism. Thus
SAML protocol messages that contain signed content SHOULD NOT be
encoded using this mechanism. (saml2-bindings, 578-582, copy pasted from PDF)
At the same time HTTP-Redirect binding requires that a new digital signature is attached to the GET URL as parameter Signature.
This means that with HTTP-Redirect you cannot send message with Signature on message level, instead the signature is added to the URL. Therefore the whole message sent from Spring SAML to IDP is signed (check it from the data sent from the SP).
There is no standard way to force IDP to send the Response message signed on message level in addition to including signature in the assertion. In case you're using SSL/TLS the authenticity and non-repudiation of the message (characteristics of digital signatures) is provided by transport layer.

Resources