How can I get security token from uaa server using Python or Postman - cloudfoundry-uaa

How can I get security token from uaa server with user name and password. Can you give me working examples that I can use from Python and/or Postman to do three following things:
1. Log in.
2. Get the token.
3. Validate the token.
the endpoints from these uaa API docs do not work:
https://github.com/cloudfoundry/uaa/blob/master/docs/UAA-APIs.rst#verify-user-get-users-id-verify

Python:
import requests, json, jwt
client_auth = requests.auth.HTTPBasicAuth('app', 'appclientsecret')
url = 'http://localhost:8080/uaa/oauth/token'
retval = requests.post(url=url, headers={'accept':'application/json'}, params= {'username':'marissa','password':'koala', 'grant_type':'password','client_id':'app'}, auth=client_auth)
decode_token(json.loads(retval.content.decode('utf-8'))['access_token'])
def decode_token(token):
print(token)
docoded = jwt.decode(token, verify=False)
print(decoded)
Postman:
POST /uaa/oauth/token? username=marissa&password=koala&client_id=app&grant_type=password HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Authorization: Basic YXBwOmFwcGNsaWVudHNlY3JldA==
Cache-Control: no-cache

Related

Unable to access Authorization header in Svelte

I am new to Svelte, and am trying to create a login page to an API. The API takes a username and password and returns an Authorization header. I see the authorization header in the F12 developer console, and I am able to access other headers via code, but not the Authorization header. I have enabled CORS on the server for localhost:8080.
<script>
const BASE_URL = ...;
export let username;
export let password;
let result;
let status;
let body;
let token;
let contentType;
async function doPost () {
const res = await fetch(BASE_URL + 'authenticate', {
method: 'POST',
mode: 'cors',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
'username': username,
'password': password
})
});
const text = await res.text();
status = res.status;
result = text;
token = res.headers.get('Authorization');
contentType = res.headers.get('Content-type');
if (!res.ok) {
throw new Error(result);
}
}
</script>
Please log in<br>
<input type="text" bind:value={username}/>
<br>
<input type="password" bind:value={password}/>
<br>
<button type="button" on:click={doPost}>Log in</button>
<br>
Result: {result}
<br>
Status: {status}
<br>
Token: {token}
<br>
Content-type: {contentType}
Response headers are as follows:
HTTP/1.1 200
Server: nginx/1.20.0
Date: Tue, 31 May 2022 18:59:09 GMT
Content-Type: text/plain;charset=UTF-8
Content-Length: 8
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:8080
Authorization: Bearer xyz...
The page displays as follows after logging in:
Result: Welcome!
Status: 200
Token: null
Content-type: text/plain;charset=UTF-8
Server side (spring boot) has the following annotation on the authenticate method:
#CrossOrigin(origins = "http://localhost:8080", allowedHeaders = "*", allowCredentials = "true")
As you can see, I am able to access the content-type header but not the authorization header. Any assistance would be greatly appreciated.
I figured it out. I needed to add exposedHeaders = "Authorization" to the #CrossOrigin annotation on the server side.
I literally solved this exact problem today. So... I'm not entirely sure why you cannot access the cookies sent back in the HTTP response, I believe it has something to do with not allowing js access to cookie related data for security reasons.
A preliminary issue I see, is that you should be sending the API auth token to the frontend, in the 'set-cookie' header, along with sending it in the HTTP response body, which I assume is JSON for your API.
I've never seen anyone suggest sending it in the 'Authorization' header like you have. I believe you are confused. I'll try and clarify the right way to do this and why you're most likely confused.
Your backend will generate an access token of some sort upon a successful login. Like I said, you send it back in the 'set-cookie' header, aswell as in the HTTP body.
Now when you read the response on the frontend, you can retrieve the Auth token from the HTTP response body, and use it in subsequent requests to authenticate to your backend server. The way JWT tokens are expected to be sent is in the 'Authorization' header of your request. This is where you're mixed up, the 'Authorization' header is used in subsequent authenticated requests to the server, not to send the Auth token from the backend to the frontend.
Now along with setting up the 'Authorization' header, you'll most likely need to send that same token in the 'cookie' header. You can do this by using the {withCredentials: true} option with fetch. This will send the cookie you sent in the 'set-cookie' response header after a successful login attempt, back to the server on all subsequent requests where you set this option.
Hope this helps, sorry I'm on my phone, so restricted with what I can write.

Generate Access token with oauth2 authentication in Spring Boot

From my microservice implemented in Spring boot if any request is render then it should pass through some authentication mechanism. In my case , both authentication and authorization is done by 3rd party server and they have provided the require clientId and secureKey.
basically they have share the below details:
Request:
POST https://auth.abc.com/oauth/token HTTP/1.1
Content-Type: application/json
User-Agent: YourPartnerService/1.2.3
{
"audience": "https://graphql.abc.com",
"client_id": "CLIENT_ID_HERE",
"client_secret": "CLIENT_SECRET_HERE",
"grant_type": "client_credentials"
}
Expected Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "PARTNER_TOKEN_HERE",
"expires_in": 86400,
"token_type": "Bearer"
}
Approach:
Created a spring boot project
added require maven dependency for oAuth2,SpringSecurity
created a rest end point which will call that 3rd party authentication endpoint.
I am unable to generate the access token .
Please help me out to find the suitable approach to generate the access token and set it as a bearer token in cache.

How do I interpret this header in this curl request?

I'm looking at a curl request that has the following as its header. What does this mean?
curl -H 'Authorization:token token="[SOME_VALUE]"' 'https://myurl.com'
Furthermore I'm trying to use RestClient to request this URL from ruby. https://github.com/rest-client/rest-client
Normally in headers it's just a key:value, but here this seems different.
It looks like the API you want to use is adopting the HTTP Token authentication RFC.
This document was a draft and it never turned into an official standard, but there are some APIs that are using it.
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Token token="h480djs93hd8",
coverage="base",
timestamp="137131200",
nonce="dj83hs9s",
auth="djosJKDKJSD8743243/jdk33klY="
You can pass custom headers to RestClient using the header option.
api_token = "xyz"
RestClient.get "http://example.com/resource", { :Authorization => %Q{token token="#{api_token}"} }
I used %Q to allow interpolation. If it's unclear to you, you can also use something like
api_token = "xyz"
RestClient.get "http://example.com/resource", { :Authorization => 'token token="%s"' % api_token }
It will be same as key value pair. Here the key is Authorization and the value is token token="[SOME_VALUE]". That should be something like below as ruby hash copied from here.
{:Authorization => 'token token="[SOME_VALUE]"'}
You can use some additional information in headers, not just key:value. For example:
Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c
Authorization:token token="[SOME_VALUE]" can be used with API with token based authentication.
Token based authentication is when an API client uses a token identifier to make authenticated HTTP requests.
You can read more about this type of authentication here: http://blog.codeschool.io/2014/02/03/token-based-authentication-rails/

Google OAuth 2.0 returns invalid redirect_uri_mismatch when getting access_token

I am trying to exchange an OAuth one-time use code that I got from my client-side app into a access token and refresh token on my server. The response that I get is:
{
"error" : "redirect_uri_mismatch"
}
My POST request is:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code={My Code}&
client_id={My Client ID}&
client_secret={My Client Secret}&
grant_type=authorization_code
I have checked my Client ID and Client Secret against those in the API Console and they match.
I get the one-time use code on my client with the following Java code:
static final List<String> SCOPES = Arrays.asList(new String[]{"https://www.googleapis.com/auth/plus.login","https://www.googleapis.com/auth/userinfo.email"});
String scope = String.format("oauth2:server:client_id:%s:api_scope:%s", SERVER_CLIENT_ID, TextUtils.join(" ", SCOPES));
final String token = GoogleAuthUtil.getToken(c, email, scope);
I have a redirect_uri in my API Console, but since I am trying to use cross-client authorization (as described here), I deliberately left it out of the POST request as is required:
When it exchanges the code for tokens, it should not include the “redirect_uri” argument in the POST.
Any idea on what I am doing wrong?
It turns out that "should not include the 'redirect_uri' argument in the POST" does not mean to completely omit the redirect_uri field. It instead means that the redirect_uri field should have an empty value.
My new, working POST is:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code={My Code}&
client_id={My Client ID}&
client_secret={My Client Secret}&
redirect_uri=''&
grant_type=authorization_code
In my case the following - https://stackoverflow.com/a/25184995/775359 - answer was helpful:
var post_data = {
code : code,
client_id : google_client_id,
client_secret : google_client_secret,
redirect_uri : 'postmessage',
grant_type : grant_type,
};
Setting redirect_uri to postmessage solved my issue with redirect_uri mismatch.
EDIT: Another answer referencing postmessage: https://stackoverflow.com/a/18990268/775359

Unable to refresh access token : response is "unauthorized_client"

I am getting an error when I try to refresh access token:
400 Bad Request
{error : "unauthorized_client"}
From the Google token URI:
{
"error" : "invalid_request"
}
I read this answer here and the official Google documentation (which describes how a POST request should look) and I don't see any difference.
I captured my POST request (secrets removed):
POST /SHOWMERAWPOST HTTP/1.1
User-Agent: Google-HTTP-Java-Client/1.10.3-beta (gzip)
Pragma: no-cache
Host: requestb.in
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 175
Connection: keep-alive
Cache-Control: no-cache
Accept-Encoding: gzip
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
grant_type=refresh_token&refresh_token=******&client_id=*******.apps.googleusercontent.com&client_secret=******
Java code which sends the request:
RefreshTokenRequest req = new RefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(), new GenericUrl(
getSecrets().getDetails().getTokenUri()), REFRESH_TOKEN);
req.set("client_id", getSecrets().getDetails().getClientId());
req.set("client_secret", getSecrets().getDetails().getClientSecret());
TokenResponse response = req.execute();
Is there anything wrong?
PROBLEM EXPLANATION
With the hint #MartinV gave I was finally able to fix it! Because his answer doesn't explain very well how to solve it, I'm going to post it here.
The problem is because we all have generated the Refresh Token using Google's OAuth Playground, but when you click 'Authorize APIs' in the first step, it takes you to the concent screen using the Playground app. After that, all the tokens that you create can be used only by the Playground app, but of course you don't know either the Client ID or the Client Secret for that app.
SOLUTION
The solution is to make Playground to use your own Client ID and Secret. To do so, click on the Settings button:
And enter your Client ID and Secret. But, before you do that, as it says there, you need to go to the Developer's Console, find your OAuth 2.0 client IDs client, edit it and add https://developers.google.com/oauthplayground under Authorized redirect URIs. After you added that and saved the changes, go back to the playground and try to Authorize APIs. In my case it took like 15 minutes before the changes in the Authorized redirect URIs took effect.
Once you're done, don't forget to remove the Playground URI from the Developer Console!
EXTRA
Once I have done that, in Python I did this and it worked:
access_token = None
client_id = 'xxxxxxxx.apps.googleusercontent.com'
client_secret = 'xxxxxxxxxxxx'
refresh_token = 'xxxxxxxxxxxx'
token_expiry = None
token_uri = "https://accounts.google.com/o/oauth2/token"
user_agent = 'YourAgent/1.0'
credentials = client.GoogleCredentials(access_token, client_id, client_secret, refresh_token, token_expiry, token_uri, user_agent)
http = credentials.authorize(httplib2.Http())
credentials.refresh(http)
service = build('drive', 'v3', http=http)
req = service.files().list()
resp = req.execute(http=http)
I created access and refresh token in OAuth2 playground and then i copied them to my app.
It`s not allowed to have different clients for autorization and for token refresh.
Another solution using the REST API to get an access_token and then use it to interact with the REST API (e.g. add a video to a private playlist) after creating the refresh_token as described above.
import requests
import json
# according to https://stackoverflow.com/a/41556775/3774227
client_id = '<client_id>'
client_secret = '<client_secret>'
refresh_token = '<refresh_token>'
playlist_id = '<playlist>'
video_id = 'M7FIvfx5J10'
def get_access_token(client_id, client_secret, refresh_token):
url = 'https://www.googleapis.com/oauth2/v4/token'
data = {
'client_id': client_id,
'client_secret': client_secret,
'refresh_token': refresh_token,
'grant_type': 'refresh_token'
}
response = requests.post(
url=url,
data=data,
)
return response.json().get('access_token')
def add_video_to_playlist(playlist_id, video_id, access_token):
url = 'https://www.googleapis.com/youtube/v3/playlistItems'
params = {
'part': 'snippet',
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {}'.format(access_token)
}
data = {
'snippet': {
'playlistId': playlist_id,
'resourceId': {
'kind': 'youtube#video',
'videoId': video_id
},
}
}
requests.post(
url=url,
params=params,
headers=headers,
data=json.dumps(data)
)
if __name__ == '__main__':
access_token = get_access_token(client_id, client_secret, refresh_token)
add_video_to_playlist(playlist_id, video_id, access_token)
I had the same problem. The solution was to use the same client when authorizing in the application and when updating the token on the server.
Can't refresh access token for Google Calendar API on server side

Resources