How to get the OAuth2 access token using Post method - authentication

Im trying to configure oauth2 with spring security, i took an example from
https://github.com/neel4software/SpringSecurityOAuth2
now my problem is i need to get an oauth2 access token using a post method instead of get, below is how the token end point is configured in spring security xml
this is the GET method URL end point that is working
http://localhost:8080/SpringRestSecurityOauth/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=beingjavaguys&password=spring#java
and this is how the end point configuration done in spring security xml
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
in order to access it using a POST method i have tried to access below end point using
http://localhost:8080/SpringRestSecurityOauth/oauth/token
with the given parameters as a payload in rest client(i have also tried to give these parameters as header parameters)
grant_type: password
client_id: restapp
client_secret: restapp
username: beingjavaguys
password: spring#java
but each time i tried to access it using rest client it allways prompt me for a username and password which i don't know. i gave username as "beingjavaguys" and password as "spring#java" which didn't work. im using Oauth2 in first time

To generate a oauth 2.0 token with password grant_type, below is the process
credential = base64Encode(clientId:secret)
value of credential is cmVzdGFwcDpyZXN0YXBw
now here is how your request should look like,
POST /SpringRestSecurityOauth/oauth/token
HOST: localhost:8080
Authorization: Basic cmVzdGFwcDpyZXN0YXBw
Content-Type: application/x-www-form-urlencoded
Payload:
grant_type=password&username=beingjavaguys&password=spring%40java

Related

Is there a way to setup apigee to use external authentication server

Is there a way to setup apigee to use external authentication server, to better explain the situation:
we generate a token from an app (test.app.com/services/oauth2/token)
we send this token with the request to the apigee endpoint
the apigee should call (test.app.com/services/oauth2/introspect) with authentication header (basic) and with body containing the token to verify it.
Im fairly new in apigee and have not seen similar implementations in my search
I am not sure if you figured another approach to this but I would you a service callout policy to call the authentication server as below:
<ServiceCallout async="false" continueOnError="false" enabled="true" name="SC-GetAuthPass">
<DisplayName>SC-GetAuthPass</DisplayName>
<Properties/>
<Request clearPayload="true" variable="ABCDLogin">
<Set>
<Headers>
<Header name="Content-Type">application/x-www-form-urlencoded</Header>
</Headers>
<Verb>POST</Verb>
<FormParams>
<FormParam name="username">{server_username}</FormParam>
<FormParam name="password">{server_password}</FormParam>
</FormParams>
</Set>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</Request>
<Response>calloutResponseGetAuthPass</Response>
<HTTPTargetConnection>
<Properties/>
<URL>{authentication_server_url}</URL>
</HTTPTargetConnection>
Then I could just extract the token and pass it to Apigee
<JSONPayload>
<Variable name="authpass">
<JSONPath>$.</JSONPath>
</Variable>
</JSONPayload>
<Source clearPayload="false">calloutResponseGetAuthPass</Source>
Then you could just call the verification endpoint with the extracted token (I assume this would be another service callout)

Keycloak - 500 Internal Server Error- when validating a token generated by a confidential client

In the Keycloak server, we created a client that has an Access Type of confidential.
By calling /protocol/openid-connect/token endpoint with the client_id and the client_secret, we got the access_token, which was supposed to authenticate the application (client) in question in the follow-up requests.
Even though the token is valid (which I double-checked by calling the introspect endpoint), I am getting a 500 Error from the server for any request that has this access_token
So in short:
Calling this endpoint <base_url>/auth/realms/<realm>/protocol/openid-connect/token gives an access_token
Provided data: client_id,client_secret, grant_type: "client_credentials"
Calling <base_url>/auth/realms/<realm>/protocol/openid-connect/userinfo gives 500Internal Server Error
{
"error": "unknown_error"
}
Any insights on what the issue could be?
This should be fixed in Keycloak 13.0.0.
See this commit: https://github.com/keycloak/keycloak/commit/056b52fbbe5af06aab957d37405215f1f4ed6ecd
It is not quite clear from the question how you are sending the token to the userInfo endpoint, Provided that the access token you have received is valid make sure that you are sending the token in the request header. Try the below curl command:-
curl
-X GET
-H "Authorization: Bearer <Access Token>"
-H "Content-type: application/json"
http://{hostname}/auth/realms/{realm_name}/protocol/openid-connect/userinfo

Mule4 HTTP Connector and Curl/Postman/ARC getting different results

Having a bizarre issue in Mule 4.3 (Anypoint 7.5.1) using the HTTP Connector to POST to a url to and get back an access token that will be subsequently used in another call for bearer authentication.
The returning access_token when using the Mule4 HTTP Request is 1277 characters, whereas every other tool I have tried, Curl, Postman, Advanced Rest Client all return an access_token that is 1266 characters.
The larger token (from Mule) is not valid and fails subsequent requests with a 401. Wheres the smaller token (from Curl/Postman) is valid and can be copied into the Mule flow and pass authentication.
I am at a complete loss as to where the extra 11 characters in the access_token are coming from.
This is the request in Mule
<http:request
method="POST"
doc:name="get-authToken"
doc:id="e7a7fe05-4085-4d43-a2ee-998364ea7518"
config-ref="Workforce_Auth_Configuration"
path="/connect/token"
sendBodyMode="ALWAYS" target="authToken" targetValue="#[message]" requestStreamingMode="NEVER" outputMimeType="application/json" outputEncoding="UTF-8">
<http:body><![CDATA[#[%dw 2.0
output application/x-www-form-urlencoded
---
{
client_id: Mule::p("secure::workforce-api.client_id"),
client_secret: Mule::p("secure::workforce-api.client_secret"),
grant_type: "password",
scope: "openid profile api offline_access",
username: Mule::p("secure::workforce-api.username"),
password: Mule::p("secure::workforce-api.password")
}]]]></http:body>
<http:headers ><![CDATA[#[output application/java
---
{
"Accept-Encoding" : "gzip, deflate, br"
}]]]></http:headers>
</http:request>
<logger level="INFO" doc:name="Logger" doc:id="afafbd11-1081-4525-a32d-ef1a98284d81" message="********* GOT AUTH TOKEN *********"/>
<logger level="INFO" doc:name="authToken" doc:id="9f03d5dc-fe8f-40b1-be11-b0ea60526703" message="#[vars.authToken.payload.access_token]"/>
<logger level="INFO" doc:name="sizeOf" doc:id="df6879cf-ab78-4823-a6bb-072e84eb8c64" message='#["********* SIZE OF AUTH TOKEN " ++ sizeOf(vars.authToken.payload.access_token) as String]'/>
The logs end up with
LoggerMessageProcessor: ********* GOT AUTH TOKEN *********
LoggerMessageProcessor: eyJhbGciOiJSUzI1NiIsImtpZCI6ImNkYTlkODUyYjdmNGIyNWFlYTZlMjg4NmM2MGQzMTRlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ4MjI2MTcsImV4cCI6MTU5NDgyNjIxNywiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb206NDQzIiwiYXVkIjpbImh0dHBzOi8vYWNjb3VudHMuZXhwcmVzc3Byb3MuY29tOjQ0My9yZXNvdXJjZXMiLCJhcGkiXSwiY2xpZW50X2lkIjoiZXhwcmVzc21vYmlsZSIsInN1YiI6ImQ4YjQ3OGJhLWQyMGUtNDljMi0zMTIzLTA4ZDRjOGQ4MjcyZCIsImF1dGhfdGltZSI6MTU5NDgyMjYxNywiaWRwIjoibG9jYWwiLCJuYW1lIjoia2xydXNzZWxsIiwiZGlzcGxheV9uYW1lIjoiS3Jpc3RvcGhlciBSdXNzZWxsIiwidXNlcl90eXBlIjoiV29ya2ZvcmNlIiwiZ2l2ZW5fbmFtZSI6IktyaXN0b3BoZXIiLCJmYW1pbHlfbmFtZSI6IlJ1c3NlbGwiLCJlbWFpbCI6ImtydXNzb2tjQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoiVHJ1ZSIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL21vYmlsZXBob25lIjoiNDA1Mjg2NDQ0NSIsIm1vYmlsZXBob25lX3ZlcmlmaWVkIjoiVHJ1ZSIsImlzX2FjdGl2ZSI6IlRydWUiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.QwREQmLZ2s7UjRwW07SkgFvvLu8fLgYmLag-XALBTM60y74oJpRLSq9vnDP8KEF33ATKiKxJP-A_lPqYWTHSAmF9HJDBA_KqIQ8Igo-9Vd5Xl_nU2ldcM5DBcoOrbudROYII70cmF7njU937EOcJ4STJ2cvTJnKZ8_xmT1A1cr5B7_IxsTMQJ2IzfCYh62RMks3_dqqZb5LZ4z4w7KTHZAwYtBFF6EdaLT1cNDvn2mHacMqKwRrrjOTDIJgx-3vNlkkCgbknYtiNbZhCrYKUzZgq-hS6pI-JFXckmHCP4U2Ohhw33TzUbRrEiC_8KXDSoK1lNDHNpIND2bZX_WuLuw
LoggerMessageProcessor: ********* SIZE OF AUTH TOKEN 1277
The request returns a json object that looks like
{
"access_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6ImNkYTlkODUyYjdmNGIyNWFlYTZlMjg4NmM2MGQzMTRlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ4MjI2MTcsImV4cCI6MTU5NDgyNjIxNywiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb206NDQzIiwiYXVkIjpbImh0dHBzOi8vYWNjb3VudHMuZXhwcmVzc3Byb3MuY29tOjQ0My9yZXNvdXJjZXMiLCJhcGkiXSwiY2xpZW50X2lkIjoiZXhwcmVzc21vYmlsZSIsInN1YiI6ImQ4YjQ3OGJhLWQyMGUtNDljMi0zMTIzLTA4ZDRjOGQ4MjcyZCIsImF1dGhfdGltZSI6MTU5NDgyMjYxNywiaWRwIjoibG9jYWwiLCJuYW1lIjoia2xydXNzZWxsIiwiZGlzcGxheV9uYW1lIjoiS3Jpc3RvcGhlciBSdXNzZWxsIiwidXNlcl90eXBlIjoiV29ya2ZvcmNlIiwiZ2l2ZW5fbmFtZSI6IktyaXN0b3BoZXIiLCJmYW1pbHlfbmFtZSI6IlJ1c3NlbGwiLCJlbWFpbCI6ImtydXNzb2tjQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoiVHJ1ZSIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL21vYmlsZXBob25lIjoiNDA1Mjg2NDQ0NSIsIm1vYmlsZXBob25lX3ZlcmlmaWVkIjoiVHJ1ZSIsImlzX2FjdGl2ZSI6IlRydWUiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.QwREQmLZ2s7UjRwW07SkgFvvLu8fLgYmLag-XALBTM60y74oJpRLSq9vnDP8KEF33ATKiKxJP-A_lPqYWTHSAmF9HJDBA_KqIQ8Igo-9Vd5Xl_nU2ldcM5DBcoOrbudROYII70cmF7njU937EOcJ4STJ2cvTJnKZ8_xmT1A1cr5B7_IxsTMQJ2IzfCYh62RMks3_dqqZb5LZ4z4w7KTHZAwYtBFF6EdaLT1cNDvn2mHacMqKwRrrjOTDIJgx-3vNlkkCgbknYtiNbZhCrYKUzZgq-hS6pI-JFXckmHCP4U2Ohhw33TzUbRrEiC_8KXDSoK1lNDHNpIND2bZX_WuLuw",
"expires_in" : 3600,
"token_type" : "Bearer",
"refresh_token" : "2fcacafc7f850f5812110a921302aab08c1c8124b7d0505691bba34c969210a2",
"scope" : "api offline_access openid profile"
}
Extracting the access token, you can see that it is 1277 characters, which confirms the log entry.
Running the same request in Curl
curl --location --request POST 'https://***************/connect/token'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'client_id=***************'
--data-urlencode 'client_secret=***************'
--data-urlencode 'grant_type=password'
--data-urlencode 'scope=openid profile api offline_access'
--data-urlencode 'username=***************'
--data-urlencode 'password=***************'
Returns the following JSON
{"access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6ImNkYTlkODUyYjdmNGIyNWFlYTZlMjg4NmM2MGQzMTRlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ4MjQ4NzcsImV4cCI6MTU5NDgyODQ3NywiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb20iLCJhdWQiOlsiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb20vcmVzb3VyY2VzIiwiYXBpIl0sImNsaWVudF9pZCI6ImV4cHJlc3Ntb2JpbGUiLCJzdWIiOiJkOGI0NzhiYS1kMjBlLTQ5YzItMzEyMy0wOGQ0YzhkODI3MmQiLCJhdXRoX3RpbWUiOjE1OTQ4MjQ4NzcsImlkcCI6ImxvY2FsIiwibmFtZSI6ImtscnVzc2VsbCIsImRpc3BsYXlfbmFtZSI6IktyaXN0b3BoZXIgUnVzc2VsbCIsInVzZXJfdHlwZSI6Ildvcmtmb3JjZSIsImdpdmVuX25hbWUiOiJLcmlzdG9waGVyIiwiZmFtaWx5X25hbWUiOiJSdXNzZWxsIiwiZW1haWwiOiJrcnVzc29rY0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6IlRydWUiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9tb2JpbGVwaG9uZSI6IjQwNTI4NjQ0NDUiLCJtb2JpbGVwaG9uZV92ZXJpZmllZCI6IlRydWUiLCJpc19hY3RpdmUiOiJUcnVlIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImFwaSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.H9TEAtoKdXkHlcCMDSn_yVKLigF0m-OhUJpnQE202QSEUkmwPJqU28-Dy8neJen6gHpqChZ-nuQmffTONrelQRG6ASh9lO9jiA8_9AzWeJ54eHBF52sSsf36E149MAyDd9yK-K2Umzfk9U9Ob9bW0OX04ih4wvTo7X-lAifk9P4SZrjRgYsVL9IGumSMI6G3EFrshHORuYqL2QjhRVtaCr_A9cAieCzarztEjyvEIYCPHmkxY-P0xAQvhnrplEBbqvoGTajEuDeuCPQ4cSeM1LSYjJpKnST46zfkUoBc-7aztusWnvCF7zbzLleDN7CcvIn8-3JnXqNt-GO_Al5plA","expires_in":3600,"token_type":"Bearer","refresh_token":"311de44f613b547efc9172d3d3d6e7f587706d77804468a426954ef19d9e3f62","scope":"api offline_access openid profile"}
Extracting the access_token here shows it is 1266 characters.
If I copy this token and use in it in the subsequent Mule Requests, the requests are authorized and proceed as expected.
I thought that this could be an encoding issue, so I set the outputMimeType to application/json and the outputEncoding to "UTF-8", but it does not seem to make a difference.
Any thoughts on what could be causing this?
EDIT
After the recommendation to enable Wire Logging, I noticed that the content-lengths are different.
The Mule4 content-length is 171, whereas Curl and Postman are 177.
It looks like Mule is converting the scope from this script
%dw 2.0
output application/x-www-form-urlencoded
---
{
client_id: Mule::p("secure::workforce-api.client_id"),
client_secret: Mule::p("secure::workforce-api.client_secret"),
grant_type: "password",
scope: "openid profile api offline_access",
username: Mule::p("secure::workforce-api.username"),
password: Mule::p("secure::workforce-api.password")
}
to scope=openid+profile+api+offline_access
whereas Curl and Postman are using scope=openid%20profile%20api%20offline_access.
Could this be the issue?
If I try to make Mule4 to use the %20 in place of the '+', it turns into scope=openid%2520profile%2520api%2520offline_access which then gives me an invalid scope error.
EDIT
I don't think that is the issue. I stripped the profile down to just api and compared the results.
This time the content-lengths on the request are the same, however the access_tokens are still different by 11 characters.
The Curl/Postman token works whereas the Mule one does not.
Enable HTTP wire logging in the Mule 4 application and use verbose (-v) in the curl command line to compare both requests and responses raw. There might be some small difference in the requests. Also compare the headers in both.
Be sure to use the latest version of the HTTP connector just in case.
UPDATE:
Based on this new comment
scope=openid+profile+api+offline_access
whereas Curl and Postman are using
scope=openid%20profile%20api%20offline_access.
It looks like DataWeave is using this interpretation of URL encoding for forms while Curl is using percent encoding. It is a bit unclear but seems that both are valid.
I don't see any option to change the way it is encoding. It is a hack but you could replace the plus signs as text and see if that helps:
%dw 2.0
output text/plain
---
write({
password: "xxx",
scope: "openid profile api offline_access"
}, "application/x-www-form-urlencoded") replace "+" with ("%20")

WebDAV return 401 - How to authenticate?

I have a problem with WebDAV. I have to get a list of files. I have this request:
<?xml version="1.0"?>
<D:searchrequest xmlns:D = "DAV:">
<D:sql>
SELECT "DAV:displayname" FROM "address" WHERE "DAV:ishidden" = false AND "DAV:isfolder" = false
</D:sql>
</D:searchrequest>
Response:
401 - Unauthorized: Access is denied due to invalid credentials.
I have user and password (who has access), but I don't know, how I can put this data to XML request.
WebDAV uses an HTTP authentication.
So you put your credentials to an HTTP header, not to the WebDAV XML in the HTTP body.
The basic HTTP authentication works like:
You get a WWW-Authenticate header from the server
WWW-Authenticate: Basic realm="server"
You include the Authorization header to the next request. The value of the header is:
Authorization: Basic username:password
where the username:password is in Base-64 encoding.
Authorization: Basic dXNlcjpwYXNzd29yZA==
For details, see
Basic access authentication on Wikipedia
RFC 7235: Hypertext Transfer Protocol (HTTP/1.1): Authentication

Spring security ldap authenticate

I have set up an ldap authentication using the following configuration. I just need to user to authenticate to the LDAP data store, then have their session get an authentication token. From reading the docs, this is what I am thinking is supposed to happen:
applicationContextSecurity.xml
<ldap-server id="contextSource"
url="ldap://192.168.0.1:389/DC=cn,DC=bleum,DC=com"
manager-dn="cn=buddy,ou=Neil,OU=Development,OU=Micosoft,DC=cn,DC=Micosoft,DC=com"
manager-password="A,1234567890" />
<authentication-manager alias="authenticationManager" erase-credentials="true">
<!--<authentication-provider user-service-ref="securityManagerSupport"/> -->
<ldap-authentication-provider server-ref="contextSource" role-prefix="none" user-search-filter="(uid={0})"
user-search-base="ou=Neil,OU=Development,OU=Micosoft" user-context-mapper-ref="contextMapper">
</ldap-authentication-provider>
</authentication-manager>
<beans:bean id="contextMapper" class="com.micosoft.neil.security.UserDetailsContextMapperSupport"/>
Error:
[DEBUG,FilterBasedLdapUserSearch] Searching for user 'test', with user search [ searchFilter: '(samaccountname={0})', searchBase: 'dc=company,dc=com', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
[DEBUG,AbstractContextSource] Got Ldap context on server 'ldap://adapps.company.com:389/dc=company,dc=com'
[INFO,SpringSecurityLdapTemplate] Ignoring PartialResultException
[DEBUG,XmlWebApplicationContext] Publishing event in Root WebApplicationContext: org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent[source=org.springframework.security.authentication.UsernamePasswordAuthenticationToken#488b5f0b: Principal: test; Password: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 0718B7EED3F930C63C03DA97C4344CBD; Not granted any authorities]
[DEBUG,UsernamePasswordAuthenticationFilter] Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
[DEBUG,UsernamePasswordAuthenticationFilter] Updated SecurityContextHolder to contain null Authentication
[DEBUG,UsernamePasswordAuthenticationFilter] Delegating to authentication failure handlerorg.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler#395158
[DEBUG,TokenBasedRememberMeServices] Interactive login attempt was unsuccessful.
[DEBUG,TokenBasedRememberMeServices] Cancelling cookie
From the result, it looks like the password was incorrect, so if you were trying to enter an incorrect user / password, then yes, that is what is expected.
Really not sure what your question is though? Were you expecting something different? Did you pass the correct credentials?
I have the same error with pretty much the same configuration. I can't give you an answer yet (sorry!), but running a debugger through the Spring classes, it seems they're trying to compare the password the user entered as a string (and the debugger confirms it is the correct password) to a password retrieved from LDAP - which is null - which then fails.