Getting error 502 when using REST API to retrieves list of all applications - ibm-mobilefirst

GET /imfpush/v1/apps HTTP/1.1
Host: mobilefoundation-3b-mf-server.mybluemix.net
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImp....
Content-Type: application/json
another type of invocation
curl -X GET -H "Authorization: Bearer eyJhbGciOiJSUzI1N...." "https://mobilefoundation-3b-mf-server.mybluemix.net/imfpush/v1/apps"
Error 502: Failed to make token request, reason: Unsuccessful request to Authorization Server, server responded with status code: 400 and body : {"errorCode":"invalid_client"}, check the Authorization URL: http://localhost:8080/mfp/api/az/v1/token

TL;DR: right now looks like there is a bug in the /imfpush/v1/apps endpoint where it does not filter the applications by the vendor (APNS, GCM, WNS), so you can only get a list of all applications instead...
Note however that it all depends on your end goal. You can accomplish this by code or by using tools such as curl or Postman, Swagger etc... it all depends on what you want to achieve.
Here are 3 ways:
In the local development server - not available in Mobile Foundation service on Bluemix, you can use this URL to see the REST endpoints exposed in Swagger. You can then view push-enabled applications with this one: http://localhost:9080/doc/?url=/imfpush/v1/swagger.json#!/Applications/getAllApplications
First, in MobileFirst Operations Console > Runtime Settings > Confidential clients:
Add (just an example, choose your own) a new user client (id: user, secret: user)
Add the apps.read and push.application.* scopes
Be sure to click on the knob and add the apps.read and push.applications.* scopes.
You will also be asked to authorize. Use the username and password for the user confidential client that you previously created.
Using the /imfpush service, as described below.
Using the mfpadmin service, as described below.
In my examples I will use Postman.
In MobileFirst Operations Console > Runtime Settings > Confidential clients:
Added (just an example, choose your own) a new user client (id: user, secret: user)
Added the apps.read and push.application.* scopes
Obtained an access token by making a POST request to http://localhost:9080/mfp/api/az/v1/token with:
Authorization tab:
Type: Basic Auth
user: user
password: user
Body tab:
x-www—form-urlencoded
grant_code: client_credentials
scope: apps.read push.application.*
Obtained the list of applications by making a GET request to http://localhost:9080/imfpush/v1/apps with:
Headers tab:
Authorization: Bearer the-access-token-from-step-2
To filter the list by platform, the URL should change to the following, like the example in the API documentation: http://localhost:9080/imfpush/v1/apps/?expand=true&filter=platform==A&offset=0&size=10 But since this does not work right now... use: http://localhost:9080/imfpush/v1/apps/
Of course, you need to change localhost to your server's host.
To only obtain a list of all applications, it'd be faster to use the mfpadmin service applications endpoint. Using Postman:
Created a new GET request to http://localhost:9080/mfpadmin/management-apis/2.0/runtimes/mfp/applications
You can change the domain to yours.
In the Authorization tab, I have set the following:
Type: Basic Auth
Username and Password: your username and password (to the console)
In return I have received a list of registered applications.

Related

Keycloak: Authorization between services and the public frontend

I have an application which consists of a frontend and several backend services. The authentication is done via Keycloak.
The workflow looks like this:
The user logs into the frontend and gets a token from Keycloak. This token is sent to the backend with every request.
The following image explains the current architecture:
In Keycloak I have the following clients:
1. Frontend
Access Type: public
Client Protocol: openid-connect
2. Core Service
Access Type: bearer-only
Client Protocol: openid-connect
3. User Service
Access Type: bearer-only
Client Protocol: openid-connect
How can I validate calls between services now?
I would imagine something like a service account and these have the possibility to call each other independently from the bearer-token from the frontend. The problem is that both services can be called from the frontend as well as between each other.
Edit:
My API is written with NestJS.
The API of the user-service:
And this is how I call the user-service in my core-service:
and this is my keycloak configuration for the the user-service:
At the moment I don't add anything to the request and I don't have any extra configuration on the interface. So I added the #Resource('user-service')-Annotation to the Controller and the #Scope()-Annotation to the Endpoint.
After that I don't get an error immediately and the endpoint is called.I can log that the logic is executed. But as response I still get a 401 Unauthorized Error.
Do I need to specify a scope or what do I need to add in the #Resource-Annotation?
Edit 2:
I'll try to show you my current situation with many screenshots.
Initial situation
Here is your drawing again. For me, points 1-5 work and point 8 works even if I do not call another service.
My Configuration
That this works, I have the following configuration:
Just Frontend and Core Service
Frontend:
Core-Service:
For the core service (gutachten-backend), I do not need to make any further configurations for this. I also have 2 different roles and I can specify them within the API.
Using Postman I send a request to the API and get the token from http://KEYCLOAK-SERVER_URL/auth/realms/REALM_NAME/protocol/openid-connect/token.
These are my 2 testing methods. I call the first one and it works. The following is logged. Means the token is validated received and I get Access:
Calling the user service
Now I call the second method. This method calls the user-service.
This is my request in the core-service:
I do not add anything else to my request. Like a bearer token in the header.
The endpoint in the user service is just a test method which logs a message.
This is my configuration for the user service:
I have now tried something with resources, policies and permissions.
Resource
Policies
Role-Policy
Client-Policy:
Permission
And analogously the client permission
Questions and thoughts
All steps from the first drawing seem to work except 6 and 7
Do I need to add more information to my request from core service to user service?
How to deal with root url and resource urls?
In the code in the API, do I need to additionally configure the endpoints and specify the specific resources and policies? (NestJS offers the possibility to provide controllers with a #Resource('<name>') and endpoints with #Scopes([<list>]))
Additionally, through a tutorial on setting up keyacloak in NestJS, I turned on the following config:
This adds a global level resource guard, which is permissive.
Only controllers annotated with #Resource and
methods with #Scopes are handled by this guard.
Keycloak's Token Verification API can do it.
This is one of Architecture for Authorization of resource access permission.
Between Core Service and User Service, Core Service needs to verify the access-token to Keycloak.
It means this token can access the User service API Yes(Allow) or No(Deny)
This is API format
curl -X POST \
http://${host}:${port}/realms/${realm}/protocol/openid-connect/token \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience={resource_server_client_id}" \
--data "permission=Resource A#Scope A" \
--data "permission=Resource B#Scope B"
Demo Keycloak Token URL: localhost:8180
Authorization Enabled Realm: test
Authorization Enabled Client: core-service
Client Resource: resource:user-service
User1 : can access it (ALLOW) password: 1234
User2 : can access it (ALLOW) password:1234
Steps
Get User Access Token(instead of login) ->
Preparations
ready to assign access-token(named user-token) variable in Postman
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("user-token", jsonData.access_token);
Get Token URL from Keycloak UI, click the Endpoints
Get User1's access token
with Bearer Token option with {{user-token}} in Authorization Tab
Verify with user1 token from Core Service to Keycloak
return 200 OK from Keycloak (ALLOW) - it is Circle 4 and 5 in my Architecture.
So Core Service forward API call to User Service for accessing service
Note - needs to finish Keycloak Permission setting
Verify with user2 token from Core Service to Keycloak
return 200 OK from Keycloak (Allow) too.
So Core Service return an error to Front-end, like this user can't access a resource of User Service.
More detail information is in here
Keycloak Permission setting
Create Client
Create Client Resource
Add Client Role
Add Client Policy
Add Permission
All user mapping into Client role
This is Configuration in Keycloak
Create Client
Create Client Resource
Add Client Role
Add Client Policy - role based
Add Permission
All user mapping into Client role - any user if you want to add to access the resource.
For people who have the same problem in the future. The answer from #BenchVue helped a lot to understand the concept in general.
What was missing is that a token must also be added for each request between services. Namely the token of the client.
So before the request is sent, the following query takes place. This is the method to get the token for a client:
getAccessToken(): Observable<string> {
const header = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
return this.httpService.post(
'{{keycloakurl}}/auth/realms/{{realm}}/protocol/openid-connect/token',
`grant_type=client_credentials&client_id={{clientId}}&client_secret={{clientSecret}}`,
header).pipe(
map((response) => {
return response.data.access_token as string;
}
));
}

Authorizing API Requests to 3rd Party Services in Mongodb Realm

I'm building a React app that allows users to login with Google and then connects to a webhook/3rd Party service in Realm. The service should only return data that the users own.
I've set up the OAuth 2 with Google and can get back access_token for a user and I then pass it in the header (I've also tried the URL params) to the webhook. But I get an error back saying:
400 "no authentication methods were specified" - "Invalid Parameter".
After much testing, I've identified that it must be a Realm issue - but I can't figure out what.
I've tried authenticating with Google in Postman and sending a request from there like this:
GET <incoming_webhook URL>
Request Headers
Authorization: Bearer <access_token>
User-Agent: PostmanRuntime/7.26.10
Accept: */*
Host: us-east-1.aws.webhooks.mongodb-realm.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
But I get the same error.
In Realm I have "Google" enabled as an authentication providers (and the authentication works just not the authorization through the webhook).
Per https://docs.mongodb.com/realm/services/configure/service-webhooks/#configure-user-authentication, you can choose email/password, an API key, or a custom JWT token. I don't know whether you can use google login directly to a webhook, but you're probably better off making a realm function instead.
Regarding the error no authentication methods were specified, you can specify the type of authentication method (using a custom JWT as an example) by either:
putting it in the header:
Header: jwtTokenString, Value: eyJhbGci.....
OR
by including it as part of the webhook body:
{
"jwtTokenString":"eyJhbGci...",
"mydata": "my data value"
}
If you try to use both methods, you get a multiple authentication methods used error. HTTP Bearer tokens in the header, etc, are useless here.
For an API Key, instead of jwtTokenString, use api-key; or email`password` for email\password authentication.
I found these methods of providing authenticating information really unintuitive and the documentation very unclear.

Azure AD Bearer invalid_token error using Postman

I am really new to Azure AD. I have read the Azure AD documentation which provides information on authentication and accessing web API's.
What I want to do : I want to use Dynamics CRM API to create a lead or contact through AWS Lambda. Meaning, whenever the Lambda function is ran, it should call the CRM API. The way I need to create a lead is with username and password creds included in Lambda. I am not sure which application scenario I need to use when I am using AWS Lambda as the source to access the web api. I want to pass the user creds with POST request.
Creating an application in Azure AD : So, I am not sure which application type I need to use (Web API or Native App?). And what should be the sign-on URL or Redirect URI?
I have tried creating an application and use Postman as the temporary way just to test whether I can get the access token and access the web api. I could able to get the access token but when I tried to access the API it says
Bearer Error invalid_token, error validating token!
I have given enough permissions while creating application in Azure AD to access Dynamics CRM API. But still unable to access the API.
POST request to get access token through Postman:
request: POST
URL: https://login.windows.net/<tenant-id>/oauth2/token
Body:
grant_type: cliet_credentials
username: xxxxx
password: xxxxxxx
client_id: <app id>
resource: <resource> //I am not sure what to include here
client_secret: <secret_key>
I get the access token in the response. Sending the second POST request using the access token
request: POST
URL: https://xxx.api.crm.dynamics.com/api/data/v8.2/accounts
Headers:
Content-type: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
Authorization: Bearer <access_token>
Body:
{
"name": "Sample Account",
"creditonhold": false,
"address1_latitude": 47.639583,
"description": "This is the description of the sample account",
"revenue": 5000000,
"accountcategorycode": 1
}
It would really help me if I can get a bit more information on where I am stuck. I have already used my one week of time to get this done. Any help will be appreciated.
To do Server-to-Server (S2S) authentication , the application is authenticated based on a service principal identified by an Azure AD Object ID value which is stored in the Dynamics 365 application user record. Please click here and here for detail steps and code samples.

How do I pass credentials to Sonar API calls?

When I try to call:
https://sonar.mydomain.com/api/resources?resource=com.mydomain.project:MY&metrics=ncloc&format=json
I get
{"err_code":401,"err_msg":"Unauthorized"}
How do I pass my credentials?
According to the newest documentation said: SonarQube now support two way authentication:
User Token
This is the recommended way. Token is sent via the login field of HTTP basic authentication, this way will be more safety, without any password. For more information about how to generate a token, please visit this page User Token. Use curl send request like this:
curl -u THIS_IS_MY_TOKEN: https://sonarqube.com/api/user_tokens/search
# note that the colon after the token is required in curl to set an empty password
HTTP Basic Access
Login and password are sent via the standard HTTP Basic fields:
curl -u MY_LOGIN:MY_PASSWORD https://sonarqube.com/api/user_tokens/search
According to the documentation SonarQube uses basic authentication. Try:
curl -u admin:SuPeRsEcReT "https://sonar.mydomain.com/api/resources?resource=com.mydomain.project:MY&metrics=ncloc&format=json"
Obviously the mechanism for passing these credentials is dependent on how you are invoking the API.
This should also work from the web browser. Try logging into the Webui, your browser will normally cache the credentials.
This happens because authentication data does not include in your api call. This is how I solved it.
1.First install a rest client "Postman" to your browser.
2.Open it and put your API call url under "Normal" tab.
3.Go to "Basic Auth" tab and put username,password then click refresh headers.
4.Come back to "Normal" tab. You'll see a header named "Authorization" in header list.
5.Now click "send" button to view results.
6.If you are using 3rd party application, add "Authorization" header to your call with the value generated by postman.

WSO2 API Manager not directing to Sandbox based on Sandbox Key

We have a deployed API which is responding correctly; however it has a different URL endpoint configured for Sandbox vs Production.
When I curl a request to the API Manager it is always the Production endpoint which is hit despite which Bearer token I submit. Authentication is working as if I submit an invalid Bearer token I get unauthenticated errors.
Any clues of where the mis-configuration might be?
(version 1.4.0)
When looking at your mentioned issue,I think you have used the 'PRODUCTION' scoped access token to invoke your SANDBOX endpoint.
After you defined two different endpoints as sandbox URL and production URL when creating the API,to invoke them you need to use different access tokens based on its scope [PRODUCTION/SANDBOX].
To invoke SANDBOX endpoint from your API,you need to use SANDBOX access token.
To find these production and sandbox endpoints related keys,you can navigate to APIStore->My Subscriptions page and view the keys under sections of 'production' and 'sandbox' in the particular subscription.And under each 'PRODUCTION/SANDBOX' keys section of subscriptions page,you'll see a separate access token and consumer key/secret.
Try invoking your SANDBOX endpoint of API,with above shown sandbox access token in 'My Subscriptions' page of APIStore or else you can use sandbox based consumer key/secret to generate sandbox scoped user tokens[1] and use those tokens to invoke your API sandbox based endpoint.
A sample cURL request to generate sandbox scoped user token would be as below;
curl -k -d "grant_type=password&username=xxx&password=xxx&scope=SANDBOX" -H "Authorization :Basic base64encoded_SANDBOX_based_consumer key:secret, Content-Type: application/x-www-form-urlencoded" https://ip:8243/token
[1] http://docs.wso2.org/wiki/display/AM140/Token+APIs#TokenAPIs-GeneratingusertokensGenerating