Getting 401 when try to update user data in Keycloak - keycloak

I am sending a put request to update partial user data but I'm keep getting 401 even though I am passing the bearer token of admin.
code:
def update_user(user_id, user_data):
import requests
headers = dict()
headers['Content-Type'] = 'application/json'
data = {
"grant_type": "password",
"username": "admin",
"password": os.getenv("KEYCLOAK_ADMIN_KEY"),
"client_id": "admin-cli"
}
token = _request("POST", f"{server_internal_url}realms/master/protocol/openid-connect/token", None, data=data).json()["access_token"]
headers["Authorization"] = f"Bearer {token}"
here = requests.put(admin_url+f"/users"+"/{user_id}".format(user_id=user_id), data=json.dumps(user_data),
headers=headers, verify=False)
print(here)

Related

JWT Authentication with Swagger .NET Core 6

I am trying to develop an application. For Authentication I am using JWT Token. I have successfully created token. And using Postman I can authenticated. But Swagger I did whatever I should do but, It doesn't work.
After authenticated as you can see,The lock icon in the upper right is active, but the lock icons on the right of the endpoints do not work.
You can find the code part below:
JWT Authentication Part:
//JwtAuthentication
var tokenOptions = builder.Configuration.GetSection(TokenOptions.OptionSectionName).Get<TokenOptions>();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidIssuer = tokenOptions.Issuer,
ValidateIssuer = true,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = SignService.GetSymmetricSecurityKey(tokenOptions.SecurityKey),
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
Swagger Gen Section:
{
options.SwaggerDoc("V1",new OpenApiInfo{
Version = "V1",
Title = "Educal API",
Description = "Main API Documantation of Educal API"
});
options.AddSecurityDefinition("Bearer,", new OpenApiSecurityScheme
{
Description = "Please insert your JWT Token into field",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
In = ParameterLocation.Header,
Scheme = "Bearer",
BearerFormat = "JWT"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme{
Reference = new OpenApiReference{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[]{}
}
});
});
And Finally Swagger and Swagger UI section:
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("/swagger/V1/swagger.json","Main API Documantation of Educal API");
});
Token is created successfully. When send a request from swagger to an endpoint Authorize tag I realized that swagger don't add to parameter.
For example:
curl -X 'GET' \
'https://localhost:7086/api/Manager/e1433dd0-ad45-456f-97e1-9f074e665feb' \
-H 'accept: */*'
By the way when sending request from Postman with header contains token, I can get to result.
Updated: https://stackoverflow.com/a/62337464/13490329 This answer solved my problem.

Amadeus flight API authorization

I am trying to use one of the Amadeus flight API (flight lowest-fare search) and I think I am having issues with the authorization. The first part of the authorization works fine where I have to input the grant type, API key, and API secret. This returns the access token needed to return the flight API. However, when printing the response body I keep getting null. Could someone help me with this? I am showing my API key and API secret but that's not an issue as I can create a new one. Here's the code:
To first provide context, here's how an Amadeus API gets called after access token is retrieved from the authorization server. This endpoint returns a flight's check-in links.
curl -X GET \
"https://test.api.amadeus.com/v2/reference-data/urls/checkin-links?airlineCode=1X" \
-H "Authorization: Bearer CpjU0sEenniHCgPDrndzOSWFk5mN"
I believe my issue might in my authorization header in the flight low-fare search endpoint. I concatenated the two variables in which the token_type which has a value of 'Bearer' and the access token. In the curl example, 'Bearer' is within the speech marks. In flutter, you cannot do that as 'Authorization is the only header. Below is my code in dart:
getFlights(fromCode, toCode) async {
// getting access token
var response = await http.post(
'https://test.api.amadeus.com/v1/security/oauth2/token',
body: {
"grant_type": "client_credentials",
"client_id": "cxuxBmIvbpbv0JKzKTsJjNqc595uJVYb",
"client_secret": "buhj4SDGVrG1AzzV",
},
);
if (response.statusCode == 200) {
try {
print(response.body);
var code = jsonDecode(response.body);
if (code != null) {
var tokenType = code['token_type'];
print(tokenType);
print(code['access_token']);
var token = code['access_token'];
var bearerToken = '$tokenType ' + '$token';
print(bearerToken);
// flight low-fare search endpoint
var flightApi = await http.get(
'https://test.api.amadeus.com/v1/shopping/flight-offers?origin=LHR&destination=CDG&departureDate=2020-03-19&max=2',
headers: {
"Authorization": bearerToken,
});
var flight = json.decode(response.body);
print(flight['data']);
}
} catch (e) {
print(e.toString());
}
}
}
This the return from the authorization server which provides the access token:
{
"type": "amadeusOAuth2Token",
"username": "I REMOVED THIS",
"application_name": "I REMOVED THIS",
"client_id": "cxuxBmIvbpbv0JKzKTsJjNqc595uJVYb",
"token_type": "Bearer",
"access_token": "z8rVGOAuGaXGNUMIcVPYW76ki5Dl",
"expires_in": 1799,
"state": "approved",
"scope": ""
}
This is the return for the flight low-fare search endpoint
flutter: null

401 Auth error with apps script connecting to 3rd party API

I am beating my head up trying to get this to work.
Any assistance would be appreciated.
I have tested the auth in Insomnia and Postman and its working fine but not with apps script. I am getting a "401 Authorization Required" response.
function myFunction() {
var url = "https://api.tempo.io/core/3/worklogs/project/MYPROJECT";
var token = "THISISATOKEN";
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer "+ token,
"muteHttpExceptions": true
};
var options = {
"method" : "get",
"headers" : headers
};
var response = UrlFetchApp.fetch(url,headers);
Logger.log(response);

400 InvalidAuthenticationToken on graph.microsoft.com/v1.0/me/calendars

enter image description here
Question: Why am I getting 40x when same token work on other rest calls, but not calendars. I works on emails, users etc.
I got the Access Token & Auth.
Getting Token:
authentication_endpoint = 'https://login.microsoftonline.com/'
resource = "https://graph.microsoft.com"
context = adal.AuthenticationContext(authentication_endpoint + tenantId)
token_response = context.acquire_token_with_client_credentials(resource, clientId, clientKey)
access_token_gmc = token_response.get('accessToken')
print("FD:::access_token-graphmicrosoft:", access_token_gmc)
What Works:
endpoint = "https://graph.microsoft.com/v1.0/reports/getOffice365ActiveUserDetail%28period%3D%27D7%27%29"
print("FD:O365:CalendarList-ActvUsers:" + endpoint)
headers = {"Authorization": 'Bearer ' + access_token_gmc}
response = requests.get(endpoint, headers=headers)
With same token - I tried this and it doesnt work:
endpoint = "https://graph.microsoft.com/v1.0/me/calendars"
print("FD:O365:CalendarList:" + endpoint)
headers = {"Authorization": 'Bearer ' + access_token_gmc}
response = requests.get(endpoint, headers=headers)
Error:
FD:O365:CalendarList:https://graph.microsoft.com/v1.0/me/calendars
('FD::0365:CalendarsList:', 400, u'https://graph.microsoft.com/v1.0/me/calendars')
('FD::0365:CalendarsList-Response', <Response [401]>)
('FD:0365:CalendarsList-Text:', u'{\r\n "error": {\r\n "code": "InvalidAuthenticationToken",\r\n "message": "Access token is empty.",\r\n "innerError": {\r\n "request-id": "3237....e",\r\n "date": "2018-10-24T23:06:20"\r\n }\r\n }\r\n}')
Check Image:
In your request for the token, you only use the clientid and clientkey, by this way, there is no related information about me in the token. You should add the user information(username and password) in the request body for the token, then you could use this token to do your following request.
And the required permissions:
I use the following way to get the user access_token:
And the response for the request is:
The error 404 is because there are no any calendars for me.

RC-IamErrorResponse - Account context in the query param is different from the account context in the token

I'm trying to get resource groups via an api key.
First, I authenticate to IAM...
apikey = 'myapikeyvalue'
self.log.debug('Authenticating to IAM')
url = self.iam_endpoint + '/identity/token'
data = "apikey={}&grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey".format(apiKey)
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic Yng6Yng="
}
response = requests.post(url, headers=headers, data=data)
token_type, access_token = # get token_type and access_token from response
Then I receive the account_id ...
url = self.iam_endpoint + '/v1/apikeys/details'
headers = {
"IAM-Apikey": apiKey,
'accept': 'application/json',
'authorization': '{} {}'.format(token_type, access_token),
'cache-control': 'no-cache',
'content-type': 'application/json'
}
response = self._request(url=url, http_method='get', description='_get_account_id', additional_headers=headers)
account_id = response.json()['account_id']
Next, I try to retrieve the resource_groups ...
url = self.region.rc_endpoint() + '/v1/resource_groups?account_id=' + account_id
response = self.client._request(url=url, http_method='get', description='get_resource_groups')
return response.json()
However, this results in:
{
"error_code":"RC-IamErrorResponse",
"message":"Account context in the query param is different from the account context in the token.",
"status_code":401,
"transaction_id":"7e89f6873e1bd4f92d57829e0f08f4ad"
}
Any ideas?
For some reason, returned value seems to be of the format: xxxxxxxxxxxY-YYYY and we only need the x's. This worked for me
return account_id.split('-')[0][:-1]