Keycloak API always returns 401 - api

I'm trying to interact with Keycloak via its REST API. I have the master realm and the default admin user, and a test realm. Firstly, I get an access token for the admin account and test realm:
let data = {
grant_type : 'password',
client_id : 'test-realm',
username : 'admin',
password : 'admin'
};
let headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
axios.post(
'https://someurl.com:8080/auth/realms/master/protocol/openid-connect/token',
qs.stringify(data),
headers
)
That works ok. Then I try to make a call to create a user (or do anything else) and I get a 401 unauthorized error:
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Bearer ${accessToken}`
};
data = {
rep: {
email: "test#email.com",
username: "test#email.com"
},
path: 'test-realm'
};
axios.post('https://someurl.com:8080/auth/admin/realms/test-realm/users',
qs.stringify(data),
headers
)
Is that not the correct way to include the token? Is the access token the one you use for authenticating other API calls? Shouldn't the admin account's token work for authenticating calls to other clients with the master realm? Would it be some setting in the master realm that I have to change in the admin console? Any help appreciated.

I got a 401 error because I generated the offline token by using http://localhost:8080 and then I tried to request the api by using http://keycloak:8080 which is not allowed. Unfortunately the log doesn't tell you that.
To debug JWT tokens I recommend https://jwt.io/

Is that not the correct way to include the token?
This is a correct way.
You just do something incorrectly.
Please, refer for an example from keycloak-request-token Node.js module:
https://github.com/keycloak/keycloak-request-token/blob/master/index.js#L43
You use
client_id : 'test-realm'
but there is
client_id: 'admin-cli'
there.
Also, to create a user, you should use
'Content-Type': 'application/json'
You can refer for Node.js examples of Keycloak REST API here:
https://github.com/v-ladynev/keycloak-nodejs-example/blob/master/lib/adminClient.js
Examples of other useful stuff like:
custom login
storing Keycloak token in the cookies
centralized permission middleware
can be found in the same project: keycloak-nodejs-example

I fixed it by enabling the below "Service Accounts Enabled" button under Settings for admin-cli

I had this issue and solved it by making sure that there is no more than 1 minute between the first and the second API request. So, if you are doing this manually (2 curl requests), the token may expire and you may get error 401. Nevertheless, you should use admin-cli as mentioned above.

I came this issue recently and after struggling for a while i figured. using a realm name containing white spaces will trigger 401 unauthorized error when interacting with via SDKs or API.
IN SUMMARY:
change: realm name
to: realm-name

Related

Not getting authorization code from google auth api with ruby

Recently google authorization api breaks and because of that other things affects like events on Calender.
We are using google_client_api for rails app and we have checked with other Client Id and Client Secret but still this fails to provide to authorization code in response and because of this everything. Is there anyone who can help me out with this. I
client = Signet::OAuth2::Client.new(client_options)
Client_options = {
client_id: Rails.application.secrets.google_client_id,
client_secret: Rails.application.secrets.google_client_secret,
authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
scope: 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email',
redirect_uri: callback_url
}
Not getting authorization code in response any solution.

How to authenticate through Graphiql playground

It's my first time using GraphQL and im trying to access the content of a given query but i can't acces this given query because of lack of permissions, in this case I have been given a username and a password to access this GraphQL api, and i'm able to get and verify the token using these credentials in GraphQL but my question is the following, how do I become authenticated in the API to be able to access the queries of the API?
My error is as follows.
"errors": [
{
"message": "You do not have permission to perform this action",
I believe this is something very basic, but I just not able to find a way to solve this issue.
Click HTTP Header and add your token as shown below:
{
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
you may have to remove Bearer and only use the token, it depends on how you did authorization on the server.
This is for JWT authentication in REQUEST HEADERS on GraphiQL below:
{
"Authorization": "JWT your_jwt_access_token_here"
}
If anyone stumbles upon same issue, just sending the HTTP didn't work in my case, because I had this line in my #auth-directive:
let token = req?.cookies?.token
Which would only check token from cookies and never from request-headers where I was passing the Authorization-header.
Fixed the issue by changing it to:
let token = req?.cookies?.token ?? req?.headers?.authorization

How to get daemon access token for self account

I am trying to create a web app whose main task is fixing appointment.
I do not want to access any mail data of the logged in user.
I only want to implicitly login using an outlook account (my account) to which I have admin access. I want to connect with this account, fetch its calendar events and display the events to the logged in user so that the user can select any available spots.
I have registered my app in the azure portal and provided all the application permissions (earlier I tried with Delegated permissions as well; but I guess delegated permissions are not for my use case).
Thereafter, I tried to fetch the token for my profile using:
this.http.post(`https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/oauth2/v2.0/token`,
{
client_id: 'my-client-uuid',
scope: 'https://graph.microsoft.com/.default',
grant_type: 'client_credentials',
client_secret: '****myclientsecret****'
},
{
headers: {
Host: 'login.microsoftonline.com',
'Content-type': 'application/x-www-form-urlencoded'
}
}
).subscribe(resp => {
console.log(resp);
});
as suggested in this article.
However, my request fails while doing this and states that the request body must contain 'grant_type' when I am clearly sending that.
Can someone please suggest me how I can implicitly get data from my own outlook account in a web app.
Update: I used the suggestion from this, appears that the request is going through now. However, the browser throws CORS error saying that the server didn't have appropriate headers.
Update 2: Found this link, which seems to address the exact issue I am facing. I however already have the redirect URI for SPA. The issue still persists.

Putting a react-django staging site behind basic auth, but auth clashes with token auth for endpoints

Whats the situation?
I've got staging site which is built with Django + React.
Parts of the API you have to login to access. I'm using Django's token authentication for that.
I then wanted to put the entire site behind basic auth, to prevent anyone of accidentally stumbling across it.
What's the problem?
This means I need to pass two authentication methods with my requests. This is possible as described here.
Authorization: Token lksdjf893kj2nlk2n3rl2dOPOnm, Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk
The token is set in my JS code after being provided to the user when they login in.
Basic authentication is triggered on the first page load, after this the browser stores it and I believe automatically appends it onto any requests where the server has the following header:
WWW-Authenticate: basic
I have configured Django to return the following header:
WWW-Authenticate: basic, token
This successfully causes a XHR request sent via axios to have the basic header appended, when the Authorization header is empty.
The problem is the Authorization header isn't empty, because I need to set a token value in there.
const axiosConfig = {
method: requestType,
url: `${url}`,
withCredentials: true,
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
data: payload
};
// If we're logged in then send our auth token
if (localStorage.auth_token) {
// Axios can't see the basic authentication header here so we can't append.
console.log(axiosConfig.headers.Authorization);
// Basic auth will only get sent if I don't set anything here
axiosConfig.headers.Authorization = `Token ${localStorage.auth_token}`;
}
At this point the browser doesn't seem to append the basic header anymore and so my authentication fails.
Is there a way around this?
I wanted a blanket basic auth because there's no way I can accidentally expose anything on staging, otherwise I have to rely entirely on the token authentication and robots.txt which is less than ideal.
The answer in the end was port forwarding.
I removed basic auth, turned off ports 80 and 443 and then used port forwarding to map my SSH to local host.
i.e. ssh -N -L 8755:127.0.0.1:443 user#ip_address

Call an Identity Provider API post Auth0 authentication

I am trying to follow the list of set of steps at https://auth0.com/docs/what-to-do-once-the-user-is-logged-in/calling-an-external-idp-api but despite my best effort am not able to get the access token as I am getting a error as follows:
POST https://r***s.eu.auth0.com/oauth/token 401 (Unauthorized)
when I try to obtain the access token.
My code is the following:
var data = {
client_id : '****',
client_secret : '****',
audience : 'https://r****.eu.auth0.com/api/v2/',
grant_type : 'client_credentials'
};
var config = {
json: true,
headers : {
'Content-Type': 'application/json;'
};
}
$http.post('https://r***.eu.auth0.com/oauth/token',data, config).then (
function(response) { console.log(response); }
);
The problem is that you're setting an incorrect Content-Type when doing your POST request.
The correct content type for a JSON request is the following: application/json
You're appending an extra ; character at the end which is causing the server to issue a 401 response.
Additionally, that code snippet seems to be from an AngularJS application. If that's the case there's two additional problems, due to CORS limitation unless the application domain is white-listed in the Allowed Origins (CORS) list in the client settings (Auth0 Dashboard), you won't be able to perform the request anyway. This is the first problem, but not the biggest one... if you solve this by adding the domain to the white-list you now have a client identifier and secret stored on a client-side application which means anyone can access it just by looking at the code. In almost all (probably 99.9%) situations this is just wrong.