Is there standard way to change runtime permissions for a user to be able to call certain odata resources of a SAP gateway service, other than manually writing code in every service implementation method to check if the request is allowed?
For example, based on some setting in customizing, the odata paths below /foo and /bar for user x should be forbidden, i.e. HTTP GET/POST/DELETE <host>:<port>/foo/test and HTTP GET/POST/DELETE <host>:<port>/bar/test should yield HTTP 403 for user x, but HTTP GET/POST/DELETE <host>:<port>/something should be OK.
Is there a way where this can be controlled at a single place rather than being required to implement a check in every method implementing the odata requests?
The proper place for the authorization check is in the backend method. Any authorization error should populate back to the service and yield a 403 for example.
If you for some reason don't want that, you could write your own HTTP handler and insert it in SICF to be called on all paths.
The standard role setup only allows access or no access to a service, the "pattern" access you are referring to is missing. But I can't really understand why you would want it? It will make your Odata services kind of un-predictable for the consumer, wouldn't it?
Related
I have an xAPI content made by storyline I want for the statement to be sent to a webapp instead of the LRS.
this webapp is developped using laravel, and user should be authenticated with email and password to use it.
what I did to send the statement to this app:
1.in the webapp I created an API endpoint route that use POST method.
2.in the xAPI wrapper I changed the endpoint in the configuration to the route I made in the webapp.
const conf = {
"endpoint":"here I added my api endpoint route of the webapp",
"auth":"Basic " + toBase64(""),
}
now whith any interaction with the content where a statement should be sent the request making cors error like in the picture down, I think this is authentication error, how can I add my authentication credentials to the xAPI wrapper?
Your non-LRS LRS is probably not handling preflight requests which are necessary for CORS handling. Most common LRSs will handle those requests appropriately since they expect to be accessed from additional origins. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests
Also note that you'll likely run into issues unless you also handle state requests.
Additionally unless you are requesting the credentials from the user during runtime then hard coding the credentials into the package isn't a great idea from a security perspective.
How does share know that user is not connected (and redirect him to login page)?
Even if a user is connected i'd like to check if he has some permission and redirect him to login page if not. So i'd like to know how Share manage authenticated user from session.
Can i use a filter, or listener or servlet or any other mecanism to intercept ALL url on share and check if connected user has require permission.
I'm using alfresco 5.0.d.
Thank you in advance for your help.
Depending on the authentication method being used and which services of Share are accessed (pages, proxy servlet or web scripts), there are multiple places where checks against the current user are made:
class SSOAuthenticationFilter - a servlet filter handling what it says in its name, Single Sign-On (SSO), e.g. Kerberos, NTLM or CAS / external authentication
class PageView - part of the Surf framework that checks if the current user has the required privileges for the current page (limited differentiation of guest, user, admin as defined by the page XML definition)
class SlingshotPageView - an enhancement / specialisation of the PageView class
class EndpointProxyServlet - handling authentication for any backend ReST API calls proxied via Share
classes PresentationContainer and instances of Authenticator interface - handling direct calls to any web scripts outside of normal page rendition cycles
Technically you can use a filter to intercept all servlet invocations on Share, but I it is not ideal from a maintenance point of view (web.xml is not easily extensible and overriden on upgrades). If all you are interested in are page rendition requests, you can use Surf extension modules to inject post-processing code that is able to generate redirection responses if user permissions are lacking. Via the root-scoped "status" object you can send the HTTP redirect responses and define a target location.
I'm using Glassfish 4 as a server with an AngularJS app as a client. Glassfish is exposing a REST API via JAX-RS (Jersey). I'm using Basic Authentication over an HTTPS connection. I have my own login form and am setting the Authorization header in my REST requests via JavaScript. My issue is that if I use normal web.xml based permissions (<auth-constraint> inside <security-constraint>), the responses come back with 401 with a WWW-Authenticate header (if the credentials are bad). This forces the browser to do the Basic Authentication dialog instead of my own and it appears there is no viable cross browser work around available on the browser side to stop it. So I need to somehow suppress the 401/WWW-Authenticate response.
I stopped using the web.xml based permissions, because it seems it is the Servlet level that is doing the 401 stuff. I was able to get Jersey authentication working with a filter and turning on the "RolesAllowedDynamicFeature" feature (in a matter similar to Glassfish #RolesAllowed with custom SecurityContext). That seems to work great and returns 403 for bad credentials (and thus no browser dialog). However, when I call my EJB's, they do not see the custom security context and the user I have set, so I get permission exceptions. If it matters: the EJB's are in a jar, the Jersey stuff is in a war, and both of them and bundled together in an ear. From what I can gather the only way to have the EJB's properly process credentials is to use the web.xml stuff.
I seemed to have painted myself into a corner and do not see how to make this work. Perhaps I can back out and return to using web.xml based permissions and somehow filter the servlet responses to not return 401/WWW-Authenticate? If so I could not find out how to do that. Or is there some way I can set EJB's security context? Or something else entirely? I wouldn't think using AngularJS with GlassFish and a REST API and Basic Authentication would be very unique, how does anyone do this?
Since posting this question I have found info on implementing a Servlet filter and using that to try to change the 401 response to a different status code. However, the filter never gains control if you have <auth-constraint> in your web.xml and the request is not authorized, so that did not help me. I still could not prevent the 401 responses.
But now I think I finally found the answer. I removed the <auth-constraint> tag from web.xml. I changed the Servlet filter to now extract the AUTHENTICATION_HEADER on its own and decode it (via javax.xml.bind.DatatypeConverter). Next I call HttpServletRequest.login (on the request object) with the decoded username and password. I catch the ServletException if the username/password combination is bad and use HttpServletResponse.sendError to send SC_FORBIDDEN. If I have a good login I call doFilter to continue on with processing of the request, and call HttpServletRequest.logout when it returns.
If I do this in combination with RolesAllowedDynamicFeature and annotations on the Jersey routines everything seems to work including calls to EJB's with their own security annotations.
Side note: before settling on HttpServletRequest.login I had tried to use HttpServletRequest.authenticate followed by checking the returned boolean, but when you gain control in that case the response has already been committed to be 401 and you cannot change it. I even tried passing a HttpServletResponseWrapper to authenticate to stop the commit from happening, but authenticate seems to get the response object through some other means, it seems to ignore the one you pass it (I even tried passed null and it didn't even notice).
While I was reading about interaction with Amazon S3, I came to know that request authentication with Amazon AWS is done in 2 ways
HTTP Authorization:
Using the HTTP Authorization header is the most common method of providing authentication information
Query string parameters:
Using query parameters to authenticate requests is useful when you want to express a request entirely in a URL. This method is also referred as presigning a URL.
The question is in which situation should I prefer one method over the other. Do these two authentication methods have their own advantages and disadvantages? As a developer, by using query string parameters method I can presign the URL which enables the end users to temporarily access the Amazon S3 resources by entering the presigned URL in the web browser. Can I use HTTP Authorization method to achieve the same thing? If so which method is better to use and what are their respective limitations?
Can I use HTTP Authorization method to achieve the same thing?
Sometimes. The key difference is that, as a developer, you don't always have enough control over the user agent to inject a header. The most obvious example of this is a simple GET request launched by a web browser in response to the user clicking a link. In that situation, you don't have the a ability to inject an Authorization: header for the browser to send ... so pre-signing the URL is all you can do.
Importantly, there's no information in a signed URL that is considered sensitive, so there's no particularly strong motivation to use the header instead of a signed URL. Your AWS Access Key ID is not secret, and your AWS Secret can't be derived from the other elements and the signature in a computationally-feasible time frame, particularly if you use Signature Version 4, which you should. Signature Version 2 is not officially deprecated in older regions, but newer S3 never supported it and likely never will.
When you do control the user agent, such as in back-end server code, adding the header may be preferable, because you don't need to do any manipulation of the URL string you already have in-hand.
The overview in the first AWS page says what the difference is:
Except for POST requests and requests that are signed by using query parameters, all Amazon S3 bucket operations and object operations use the Authorization request header to provide authentication information.
Basically a POST is used for HTML forms (discussed at length in the Mozilla page). You would use forms whenever the request involves passing data to the remote server, versus just checking status. As noted in HTML method Attribute (W3Schools),
Never use GET to send sensitive data! (will be visible in the URL)
as distinguished from POST:
Appends form-data inside the body of the HTTP request (data is not shown is in URL)
I'm writing a REST-ish API service the provides the ability to interact with the end user's data in other 3rd party services (themselves REST APIs) via OAuth. A common example might be publishing data from my service to a third-party service such as Facebook or Twitter.
Suppose, for example, I perform an OAuth dance with the end user and Facebook, resulting in some short-term access token that my service can use to interact with the user's Facebook account. If that access token expires and the user attempts to use my service to publish to Facebook, what sort of error do I return to the user?
401 doesn't seem quite right to me; it seems that 401 would apply to the user's auth state with MY service. 403 seems much more appropriate, but also quite generic.
401 is the way to go. Two excerpts from the RFC2616 which defines the HTTP protocol:
Section 10.4.2 (about 401):
If the request already included Authorization credentials, then the 401
response indicates that authorization has been refused for those
credentials.
This seems to be appropriate for expired tokens. There are authentication credentials, but they're refused, so the user agent must re-authenticate.
Section 10.4.4 (about 403):
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
This should be used when the resource can't be accessed despite the user credentials. Could be a website/API that works only on US being hit by a asian IP or a webpage that has been declared harmful and was deactivated (so the content WAS found, but the server is denying serving it).
On OAuth2, the recommended workflow depends on how the token is being passed. If passed by the Authorization header, the server may return a 401. When passed via query string parameter, the most appropriate response is a 400 Bad Request (unfortunately, the most generic one HTTP has). This is defined by section 5.2 of the OAuth2 spec https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26
There's nothing wrong with being generic, and it sounds like a 403 status would be relevant - there is nothing stopping you from providing a more human readable version that elaborates in a bit more detail why.
I think the following is a comprehensive list if you have some level of ambition when it comes to error responses.
400 Bad Request
For requests that are malformed, for example if a parameter requires an int between 0-9 and 11 has been sent. You can return this, and in the response body specify parameter x requires a value between 0 and 9
401 Unauthorized
Used only for authorization issues. The signature may be wrong, the nonce may have been used before, the timestamp that was sent is not within an acceptable time window, again, use the response body to specify more exactly why you respond with this. For the sake of clarify use this only for OAuth related errors.
403 Forbidden
Expressly to signify that an operation that is well formed, and authorized, is not possible at all (either right now, or ever). Take for example if a resource has been locked for editing by another user: use the response body to say something along the lines of Another person is editing this right now, you'll have to wait mmkay?.
403 Forbidden can also have to do with trying to reach resources. Say for example that a user has access to a resource /resource/101212/properties.json but not to /resource/999/properties.json, then you can simply state: Forbidden due to access rights in the response body.
404 Not Found
The requested resource does not exist. Or the URL simply does not successfully map to an API in your service. Specify in response body.
405 Method Not Allowed
This is to represent that the API can not be called with for example GET but another method must be used. When this is returned also you MUST return the extra response header Allow: POST, PUT, etc.