I have a Policy Server where I'm creating resources & roles. The resources are guided by policies which is defined based on the roles. For ex. assume we have the following resources button1, button2, Submit, table2 & Roles like Google:NA:Admin, Yahoo:CHN:Admin, Google:CHN:User, Alphabet:EU:Admin, etc.. The user will be registering for a role by logging into the Policy Server site by providing username and password. I'm getting authorized resource list for each user from a server. The response from the server will be like the following for a username "greenUser" (the only parameter sent as part of the POST request to Policy Server API).
{"permit":[
"button1",
"table2",
"Role:Google:NA:Admin",
"Submit"
]
}
The requirement is to determine the Role of the user, Region, Company & the list of resources he has access.
So, I created a resource on the same name of the "Role" and restricted the access in Policy Server for that particular Role. eg: I created a role "Google:NA:Admin" and created a policy to restrict the access to only role "Role:Google:NA:Admin". The intention is to find this resource as part of the response and to determine the Role the user is having.
There is a possibility that a user can having multiple roles. eg. He can be an admin for Google (NA region) & Alphabet (EU region).
To determine the Region and Company from the roles. I created a JSON like the following:
{
"Roles" : [{
"Google" : [{
"NA" : ["Role:Google:NA:Admin", "Role:Google:NA:User"]},{
"CHN" : ["Role:Google:CHN:Admin", "Role:Google:CHN:User"]}
]
},
{
"Alphabet" : [{
"NA" : ["Role:Alphabet:NA:Admin", "Role:Alphabet:NA:User"]},{
"CHN" : ["Role:Alphabet:CHN:Admin", "Role:Alphabet:CHN:User"]}
]
}
}
I have created a method using Java which parses the entire JSON and if the value matches to the particular "Role" resource returned, then I'm capturing the Key (eg: CHN) as the Region & the key of the outer JSON Element as "Company".
I want to check if there is a better way to determine the Role, Region & Company of the user. The above mentioned JSON is my idea. I would love to hear if there is a better design or approach other than the JSON. Example Code snippets are appreciated.
Sorry for the long post. I tried my best to capture the complete requirement.
Thanks in advance.
If the policyserver has an API to getRoles for a given User I would use that or create one instead (if possible). Adding roles as resource will be my last plan if all doors are closed.
Not clear about which system generates the company-country-roles JSON. Is it policy server or your application ? If it is policy server I would return array of policyNames (getRoles API). If your application is going to return this JSON I would discuss it with the consumer of the application service and decide if it meets their expectations. If there is no consumer I would just return array of Role Names to keep it simple
Related
A token is created with:
"oauth": {
"client_id": "...",
"redirect_uri": "...",
"scope": "p1 p2 p3 p4 p5",
"state": "...",
"code_challenge": "...",
"code_challenge_method": "..."
}
This returns a signed jwt token with the scope options.
I want to update the signed jwt with a 'selected_person' int the claims, say p1, so i call the refresh token url passing in the refresh token and scope 'p1', do some logic on the backend and set the person id. This then adds the person id to a newly signed token, all is good:
eg. /token?client_id=x&grant_type=y&refresh_token=y&scope=p1
It's possible to call the same endpoint with any of the scopes first defined (p1, p2 etc) as Spring will compare the scope to the initial list of scopes and return a refresh token if it matches.
The problem arises when a new person gets linked to me, so now i would have p6. As each refresh token call is based on the first list, p6 does not exists and will not be allowed. If i logout and get a new token then p6 gets added to the scope.
Is there anyway i can add p6 to the scope without loggin out?
EDIT:
Ultimately is there a way to update originally granted scopes?
After lots of digging for answers and solutions, the requirement is simply not possible without logging out. As the documentation dictates
scope (optional)
The requested scope must not include additional
scopes that were not issued in the original access token. Typically
this will not be included in the request, and if omitted, the service
should issue an access token with the same scope as was previously
issued.
Ref: https://www.oauth.com/oauth2-servers/access-tokens/refreshing-access-tokens/
#dale You could try a slightly different method where you hold an internal mapping to the scope. But you would have to accept initials scopes as groups. However, what you are trying to achieve will not work for two reasons.
You are trying to change a signed document which will invalidate the document (JWT). but that doesn't really matter as it is for your use only.
If the subsequent API calls are linked to authorized scopes, the calls will not validate for you.
I am working on a Play Framework Rest API, which uses keycloak for authentication and now on extending towards the authorization, i have extracted the RPT token and stored the permission access based on resource name. But now i have no idea how to map my controllers with the resource name and restrict the user to use certain functions which can only be used by admin or a different role. The structure of permission is:
"authorization": {
"permissions": [
{
"rsid": "4bxxxxxx-xxxxx-xxxxx-xxxx-xxxxxxx",
"rsname": "Default Resource"
},
{
"rsid": "8xxxxxx-xxxxx-xxxxx-xxxx-xxxxxxx",
"rsname": "admin_res"
},
{
"rsid": "cxxxxxx-xxxxx-xxxxx-xxxx-xxxxxxx",
"rsname": "superAdmin_res"
}
]
},
And i am storing all the rsname in a list and stored locally in the session.
Now i just want to control the api calls based on resource name and restricting the controller calls.
I have a KeyCloakSessionAction which extends to a action.simple, so how can i pass the auth details along with it and restrict certain controllers.
Not sure if are using any keycloak adaptor, if your are implementing one for playframework, you need not store permissions, you can directly get overall decision from token end point some thing like this
curl -X POST
http://localhost:8080/auth/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 "response_mode=decision"
Response will be
{
'result': true
}
you can more details form keycloak documentation
I found a much better solution to this using, Custom Annotation which will restrict a particular API if the user does not have access to those resources.
Kindly refer here: https://www.javatpoint.com/custom-annotation
And based on that you can set the value as the resource name and check every time a user calls an API.
For eg. #Authorization(Default Resource) over
#Authorization(Default Resource)
public class getPassword(){
...
...
...
}
Add this line Before every API Call. Here only the users with Default Resource in their session will be allow to successfully fetch the password.
I want to modify the content of a file stored in the Google Cloud Storage bucket and serve it to the user. The delivery content will change based on the User profile.
By the following ways I am trying to achieve it.
User will request for a particular hash key, this key is mapped to a cloud storage url. The contents are read, modified and served to the User when the hash key is used in the url. Say /serve/hash-key.
User will not know the cloud storage url, nor will have a direct access to the content of the file.
Java servlet is mapped in the server-side to process the User request. To process all /serve/* queries.
User can do the request either through the current tab or through a new tab.
The problem what I am facing is when the request is processed in the Java Servlet, App Engine User details could not be fetched using OAuthServiceFactory class. OAuthRequestException is thrown when getCurrentUser Api is called.
Is there a possible way to achieve this or address the error?
I am trying to make a very simple app with spring social, the app is not for public. What I am trying to achieve is to post to my wall or to the page that I administer.
Trying to ask facebook for access to manage_pages permission they denied because as they said "You do not need to request these permissions because your blog or CMS is integrated with an app that you admin. As an App admin, you can already access these permissions and post to your timeline or a page you admin. You can provide access to additional users by adding them as developers of your App."
Now in the code. I altered a bit spring social showcase example. And my case is as follows:
1) I login to facebook through my app
2) Trying to get the number of pages that I administer
3) Post to my wall.
For step two I am using this code:
if (facebook.pageOperations().getAccounts() != null) {
System.out.println("SIZE OF ACCCOUNTS IS: " + facebook.pageOperations().getAccounts().size());
}
The size of accounts is always 0. So this means that although I should be able to post to the pages that I am administrator I can not even see them. Am I correct?
For step three now:
facebook.feedOperations().updateStatus("I'm trying out Spring Social!");
facebook.feedOperations().post(new PostData("me").message("I'm trying out Spring Social!")
.link("http://www.springsource.org/spring-social", null, "Spring Social", "The Spring Social Project", "Spring Social is an extension to Spring to enable applications to connect with service providers."));
System.out.println("FEED POSTED");
both of those attempts fail with the following exception:
org.springframework.social.InsufficientPermissionException: Insufficient permission for this operation.
Could someone help please?
It seems like you have not asked/granted the permissions that you need during login. The first thing that you need to do is implement login and ensure sure that you include the correct scope i.e. permission (manage_pages) during login. Since your requirements also include publishing, include these permissions publish_pages and/or publish_actions depending on whether you want to publish as a page or yourself. e.g. if you are using the JS SDK, it would look something like this:
FB.login(function(response) {
// handle the response
}, {scope: 'manage_pages, publish_pages, publish_actions'});
Once you do this, on logging in, you will be prompted if you want to grant these permissions. On granting, your access token will contain these permissions and you will be able to make a call to /me/accounts which will give you a list of pages that you admin and their respective access tokens. It will look something like this:
"data": [
{
"access_token": "CAACEdEose0cBAAy...",
"category": "Food/Grocery",
"name": "Page Name",
"id": "1234567890",
"perms": [
"ADMINISTER",
"EDIT_PROFILE",
"BASIC_ADMIN"
]
},
...
]
If you want to publish as yourself, then you can continue using the current user access token. Else if you want to publish as a page, grab the page access token from the response above and use that to make the POST request against the page id.
And if you are creating an app for yourself and not for the public, then you do not need to submit these permissions for review provided you are an admin or have some role in the app.
You might be able to find some more context here.
I'm using Spring MVC and Spring HateOAS to make a restful and stateless JSON API.
Everything works fine. But i have a "conception" question. My API use an authentication token in every request. For example, you use the login API to get your authentication token, and when you call my API you must use it like this :
http://some_host/api/foo/bar?token=abcd
The API always respond a JSON and links are generated via Spring HateOAS. For exemple :
{
"label" : "foo",
"links" : [
"rel" : "self",
"href" : "http://some_host/api/foo/bar/1234656"
]
}
The question is : Should i add the authentication token in the generated URL ? (so it will be http://some_host/api/foo/bar/1234656?token=abcd)
I can't find any advice or convention for that.
Usually, authentication tokens are communicated via standard HTTP headers (such as the Authorization header in the case of HTTP Basic or Digest). The other common one is via a cookie. In Servlet environments, this is usually the JSESSIONID cookie.
Generally speaking, you shouldn't see authentication tokens passed as part of the request URL.
This is an old question, but the answer is definitely no.
http://some_host/api/foo/bar/1234656 is supposed to be the uniform identifier (URI) and location (URL) for that resource. It's the one URL you can rely on. You can always get the resource using that URL but you'll never get the resource with http://some_host/api/foo/bar?token=abcd again, because the token will expire.
Calling the URL with the token appended is one thing, but it should never appear in the link, because it has nothing to do with the resource. It's the client's responsibility to send the token, not the server's one.