WSO2 APIM 3.1.0 - API runs with one user but not for other user with same role - authentication

i am working on a multi-tenant app and i have two users with "admin" role. 1st user is "admin" and 2nd user is "abc". When i access token for both users, same scope is returned for both.
{
"access_token": "d479b9e3-1def-31b4-b8a8-3033ae6467ab",
"refresh_token": "887c386b-2ec7-39c4-9bcf-c286f4dfda40",
"scope": "app_non-permission app_permission portal_access",
"token_type": "Bearer",
"expires_in": 1862
}
Using this token, i call my subscribed API, and it works for "admin" user but fails for "abc". Error message for "abc" user is as below.
<ams:fault xmlns:ams="http://wso2.org/apimanager/security">
<ams:code>900910</ams:code>
<ams:message>The access token does not allow you to access the requested resource</ams:message>
<ams:description>Access failure for API: /portal/1, version: 1 status: (900910) - The access token does not allow you to access the requested resource</ams:description>
</ams:fault>
I am unable to understand why it works for one user but not for the other even though the users have same role and token API also returns same scope.

Looking at your explanation it sounds to me like the 'abc' user needs to also subscribe to the API. You might be using the wrong "grant_type" while retrieving the bearer token. [1]
Another possibility would be to add "application sharing" [2] if it's not possible for your 'abc' user to use it's own store application to subscribe to the API.
[1]https://docs.wso2.com/display/AM260/Password+Grant
[2]https://docs.wso2.com/display/AM260/Sharing+Applications#SharingApplications-Enablingapplicationsharing

Related

Leveraging REST API's stateful token-based authentication pattern in its sole client (a web application), restricting some pages to loggedin users

I'm working on a REST API and a web application that will work off said REST API. The REST API implements a stateful token-based authentication pattern. Ultimately, allowing users to exchange their user credentials for a time-limited authentication token that identifies who they are.
So for example, a request such as:
POST: http://localhost:4000/api/v1/tokens/authentication
REQUEST BODY: {"email": "my_email_address", password": "my_password"}
would yield a response like:
"authentication_token": {
"token": "GAHZQS3IEIE6ELF7IHC6GK7M5Y",
"expiry": "2022-07-19T02:49:09.4194657+01:00"
}
If the user credentials that the user entered were incorrect, the user would not receive the authentication token.
The user needs to include the token in any further requests so that the REST API can identify the user. Some API endpoints are restricted to just logged-in users/users with certain permissions. And the token allows the REST API to know what sort of user it's dealing with. The token corresponds to a user id.
There will be a separate server from the REST API server serving the web application pages. But the pages will be populated with data from the REST API via the javascript fetch API.
I am happy with the REST API authentication. But I also need to restrict access to the web application pages based on if the user has logged in or not.
I want to leverage the existing REST API authentication but have never done something like this before so would very much appreciate any input you have.
Currently, I'm thinking of doing something like what's listed below. Do ye see any problems with it?
User accesses login page, enters credentials, and clicks 'login' button.
On clicking the 'login' button a request to the REST API is made:
POST: http://localhost:4000/api/v1/tokens/authentication
REQUEST BODY: {"email": "my_email_address", password": "my_password"}
If the credentials are correct, a token is returned, such as:
"authentication_token": {
"token": "GAHZQS3IEIE6ELF7IHC6GK7M5Y",
"expiry": "2022-07-19T02:49:09.4194657+01:00"
}
This token is added to a cookie for later use. i.e for when making another request to the REST API via the fetch API.
I'm thinking of adding another REST API endpoint that will simply validate a token i.e state whether or not the passed token is still valid and that the user is still logged in.
The webpage server can then call this endpoint to ensure the token is valid before showing a user a page that is restricted to just logged-in users.
Or maybe, instead of a validate token API endpoint, I should have a 'get user by token' endpoint. That will return user data if the token is valid. That way the webpage server could also get to know the type of user account that is associated with that user and could then also restrict pages based on the user type. It might also come in use for populating pages since nearly all pages will contain some user info e.g a profile image.

MSGraph Multi-Factor Authentication "interaction_required"

I'm using the Microsoft Graph login endpoint: login.microsoftonline.com/[tenantId]/oauth2/token with a grant type of "password" to log users in:
{
"grant_type": "password",
"client_id": "xxx",
"client_secret": "xxx",
"scope": "openid",
"resource": "https://graph.microsoft.com",
"username": "username",
"password": "********",
}
When I post this with users that are not enrolled in multi-factor authentication on our AD I get back the expected results including an access_token and refresh_token
However on users that are enrolled I get back a HttpStatusCode.BadRequest with an error of "interaction_required"
According to documentation from Microsoft found here:
In this case, your app receives a 400 with an interaction_required
error during access token acquisition or a 403 with
insufficient_claims error when calling Microsoft Graph. In both cases,
the error response contains additional information that can be
presented to the authorize endpoint to challenge the user for
additional information (like multi-factor authentication or device
enrollment).
However I do not see any additional information in the results and can't find much information on next steps. The JSON I get back looks like this:
{
"error":"interaction_required",
"error_description":"AADSTS50079: Due to a configuration change made by your administrator, or because you moved to a new location, you must enroll in multi-factor authentication to access '00000003-0000-0000-c000-000000000000'.\r\nTrace ID: aee10c85-fd12-42ec-be6c-76d546500100\r\nCorrelation ID: 0ee3ebac-f702-4fbc-be76-fd6a291ad488\r\nTimestamp: 2021-09-09 17:45:24Z",
"error_codes":[50079],"timestamp":"2021-09-09 17:45:24Z",
"trace_id":"aee10c85-fd12-42ec-be6c-76d546500100",
"correlation_id":"0ee3ebac-f702-4fbc-be76-fd6a291ad488",
"error_uri":"https://login.microsoftonline.com/error?code=50079",
"suberror":"basic_action"
}
But I am getting back "interaction_required" and confirmed with our AD administrator that they are definitely enrolled. So I am at a bit of a loss for next steps to resolve this.
Cause :User is attempting a authentication method that requires Multi-factor authentication
Try to catch the error you get, and perform a new request according to steps for your flow scenarios by referring from this MS docs
Microsoft Graph has special considerations when building apps in
Conditional Access environments. Since Conditional Access policies are
assigned the specific datasets, Azure AD will enforce Conditional
Access policies based on the data behind Graph - rather than Graph
itself.
(or check below points)
Conditional access policies prevent non-interactive flows to work.
Possible solutions...
Use a interactive flow instead.
If you are using a interactive flow and still getting this error, please make sure openid is one of the scopes during the interactive sign-in. You might be getting the error after the interactive sign-in and trying to exchange the authorization code for a access token...
Example:
https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/authorize?client_id=#...#
&response_type=code
&scope=openid groups.read.all
&nonce=1234
&redirect_uri=https://app.contoso.com
Notice "scope=openid groups.read.all" in the request above
Add the client application to the exception list of the Conditional Access Policy
Add the user to the exception list of the Conditional Access Policy
If you are not using conditional access policies and the user is directly enabled for MFA, then as a last thing, disable MFA for the user if solutions above do not work for you.
Or you can use certificate based authentication instead of MFA
References:
login-to-azure-web-application-fails-with-aadsts50079
SO thread

G Suit - Token Validation like unprotect

I have an G-Suite Account..I have created a project in developer console. In that i have chosen the Oauth client Id credential for Application Type (Others). I have received client secret and Client ID..... Using this i have tried the sample mvc https://developers.google.com/drive/v3/web/quickstart/dotnet I have received the token with Below information
1.access_token
2.Experiences
3.refresh_token
4.Token_Type and so on…
I cant find any user related information (eg: UserId) in the token for Authenticate in our application (used tokeninfo api to validate token). I get below response
{
"issued_to": "123456789234.apps.googleusercontent.com",
"audience": "123456789234.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.user.readonly",
"expires_in": 3520,
"access_type": "online"
}
How to get userid in access_token?
If you are try to get their user information you have to add https://www.googleapis.com/auth/userinfo.profile in your scopes.
View your basic profile info
Here is some additional reference:
How to get user email from google plus oauth
How to identify a Google OAuth2 user?
Hope this helps.

Graph API: Either scp or roles claim need to be present in the token

I'm attempting to use MS Graph API to get a list of files/folders from OneDrive for Business. I've successfully executed the queries I need in Graph Explorer and am now moving on to implementing in my project.
My app is a Windows service, so I'm acquiring a token using this method
I've successfully retrieved a token, but when I "GET" this URL...
//graph.microsoft.com/v1.0/users('someuseraccount')/drive/items/somedriveitem/microsoft.graph.createLink
... I get a response back with the error:
Either scp or roles claim need to be present in the token.
My token response from the server is as follows:
{
"token_type": "Bearer",
"expires_in": "3600",
"scope": "Directory.AccessAsUser.All Files.Read Files.Read.Selected Files.ReadWrite Files.ReadWrite.AppFolder Files.ReadWrite.Selected profile Sites.Read.All User.Read",
"expires_on": "1457343736",
"not_before": "1457339836",
"resource": "https://graph.microsoft.com",
"access_token": "-the token-"
}
It appears that your client application has only requested delegated permissions to Microsoft Graph, whereas application permissions should be requested for the scenario attempted here. Below is an illustration of application permissions section in Azure portal. Please select appropriate permissions needed and retry.

Google credential fails to refresh token with email and profile scope

I'm using a google credential as part of the google-api-client. I'm attempting to get their email and profile using the Plus api with the https://www.googleapis.com/plus/v1/people/me endpoint. Documentation states that you can pass it the email and profile scopes and it should return the information. Though all I get is
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
Though when I use the https://www.googleapis.com/auth/userinfo.email and the https://www.googleapis.com/auth/userinfo.profile scope the call works just fine.
Building the credential as:
GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(accountId)
.setServiceAccountScopes(accountScopes)
.setServiceAccountPrivateKey(accountPrivateKey)
.setServiceAccountUser(accountUser)
.build();
And the googleCredential.refreshToken() call fails.