I currently have this blueprint as https://help.apiary.io/api_101/apib-authentication/#describing-basic-auth-in-api-blueprint described.
FORMAT: 1A
# Basic Auth API
## Basic Auth protected resource [/protected]
### Status [GET]
+ Response 401
+ Headers
WWW-Authenticate: Basic realm="protected"
+ Request
+ Headers
Authorization: Basic dTE6dDE=
+ Response 200 (application/json)
{
"status": "ok"
}
But it won't work, the api endpoint would pop up asking for username/pwd and I entered the corresponding pair u1:p1 it will just pop up the window again.
Does anyone have insight on this? Thanks so much in advance!
Related
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.
I'm new to using the rest-client. I know I'm missing something, but I am trying to do the following:
Post to a login endpoint to authenticate
After authentication, post csv text to another endpoint that requires a logged in user
The authentication portion is successful, however, I am getting a 401 Unauthorized when step 2 occurs.
rest_client = RestClient
login_response = #global_rest_client.post(
host + 'LOGIN ENDPOINT',
{ userName: 'user', password: 'password'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
)
import_response = rest_client.post(
host + 'IMPORT DATA ENDPOINT',
headers: { 'X-System-Name': 'AndroidMobile', 'Content-Type': 'multipart/form-data },
csv: csv_string
)
My understanding of how authentication works could be wrong. My assumption is that as long as the same instance of the client has a successful login, then the post of csv data would also be successful.
I appreciate any input.
HTTP (1.1) is stateless so a request does not contain any information about previous requests unless that information is encoded and added to the request in some way (e.g. cookies or headers). So when you make your import request the server does not know if/that you are authenticated even though you just made a login request.
You'll have to include the token you receive from your login request in subsequent requests. This should go in the 'Authorization' header.
For example:
auth_token = login_response["success"]["token"] # or whatever the key is for the token
import_response = rest_client.post(
host + 'IMPORT DATA ENDPOINT',
headers: { 'Authorization': "Bearer #{auth_token}", 'X-System-Name': 'AndroidMobile', 'Content-Type': 'multipart/form-data },
csv: csv_string
)
The way authentication works depends on the server and can be different in different cases. So the site you are accessing might expect the Authorization header to be like "Token #{auth_token}" or anything else, but they should mention it in their documentation.
Hello fellow programmes,
I am stuck on the issue with keycloak. I am trying to send from node.js express framework request towards keycloak to logout the user.
Config.keycloakClient = my_realm
Config.keycloakURL = keycloak URL
request.get({
//url: join(Config.keycloakURL, '/auth/realms/'+ Config.keycloakClient+ '/protocol/openid-connect/logout?' + 'id_token_hint='+req.headers.oidc_access_token), <--- tried this
url: join(Config.keycloakURL, '/auth/realms/'+ Config.keycloakClient+ '/protocol/openid-connect/logout'), // <-- i also tried this
headers:
{ Authorization: "Bearer " + req.headers.oidc_access_token, // <-- also tried Authorization: req.headers.oidc_access_token }
Result - 200 OK, but i can still see active session in active sessions in admin interface
request.post({
//url: join(Config.keycloakURL, '/auth/realms/'+ Config.keycloakClient+ '/protocol/openid-connect/logout?' + 'id_token_hint='+req.headers.oidc_access_token), <--- tried this
url: join(Config.keycloakURL, '/auth/realms/'+ Config.keycloakClient+ '/protocol/openid-connect/logout'), // <-- i also tried this
headers:
{ Authorization: "Bearer " + req.headers.oidc_access_token, // <-- also tried Authorization: req.headers.oidc_access_token }
Result - 302 redirect, but i can still see active session in active sessions in admin interface
I was trying to find the refresh token, but when accessing
Config.keycloakURL/auth/realms/{realm}
i could not get the refesh token-> it redirects me to the login page.
In session storage / cookies i can not see anything strange via chrome dev tools.
So what is the proper way to logout with endpoint? Which endpoint and what parameters should i use please? And how am i to obtain refresh token?
Thanks for the help!
Best regards
I am trying to define an API blueprint for a resource that utilises request headers to understand what content type to return.
## Offer [/offers/{offerCode}]
+ Parameters
+ offerCode: summer2015 (required, string) - alphanumeric offer code
### View an Offer Detail [GET]
+ Response 200 (application/vnd.v0.1.0+json)
{
........
}
I want my request to be as follows:-
GET /offers/summer2015 HTTP/1.1
Host: my.api.com
Accept: application/vnd.v0.1.0+json
How can I document that using API Blueprint?
I'm not sure if I understand what you want to achieve but I'd say that you want to specify header for request and you can do that by specifying request the same way as response.
## Offer [/offers/{offerCode}]
+ Parameters
+ offerCode: summer2015 (required, string) - alphanumeric offer code
### View an Offer Detail [GET]
+ Request
+ Headers
Accept: application/vnd.v0.1.0+json
+ Response 200 (application/vnd.v0.1.0+json)
{
........
}
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