Custom controller anonymous access


(Shanur Anasari) #1

Hi,

I am trying to access custom controller without token,
I am calling a custom controller to get the active token for user login id Ex: “anonymousAccessUser” it will give me if there is any active token in the database which is not expired for this user and if no active token present in the database then I am creating a new token and returning the response back which is working perfect.

But I want to access this API(custom controller) without passing any oAuth token. Below is the code for your reference please help me to correct the thing where i am making mistake

portal-security-spring.xml

<security:http pattern="/rest/myapi/**"
                   create-session="stateless"
                   entry-point-ref="oauthAuthenticationEntryPoint"
                   xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/rest/myapi/**" access="true"/>
        <anonymous enabled="true"/>
        <csrf disabled="true"/>
        <cors configuration-source-ref="cuba_RestCorsSource"/>
        <custom-filter ref="resourceFilter" before="PRE_AUTH_FILTER"/>
        <custom-filter ref="cuba_AnonymousAuthenticationFilter" after="PRE_AUTH_FILTER"/>
    </security:http>

My custom controller

@RestController
@RequestMapping("/myapi")
public class MyController {

    @GetMapping("/getUserTokenDetails")
    public String getUserTokenDetails() {
        try {
            String userLogin = "anonymousAccessUser"; //user created with this login id
            UserTokenDTO tokenDetails = utilityService.getAnonymousToken(userLogin); //calling service method which returns active token for this user
if(tokenDetails == null){
//generating new token if no active token found in databse
                OAuthTokenIssuer.OAuth2AccessTokenResult tokenResult = oAuthTokenIssuer.issueToken(userLogin,
                        messageTools.getDefaultLocale(), Collections.emptyMap());
                OAuth2AccessToken accessToken = tokenResult.getAccessToken();

                return accessToken.getValue();
            } else {
//return existing active token
                return tokenDetails.getAccess_token();
            }

        } catch (Exception ex) {
            return "No active token found"+ex;
        }
    }

Service bean method to return active token if any

@Override
public UserTokenDTO getAnonymousToken(String userLogin) throws Exception{
    String query = "SELECT ACCESS_TOKEN_VALUE, EXPIRY, AUTHENTICATION_KEY, USER_LOGIN FROM SYS_REST_API_TOKEN "
            + " WHERE USER_LOGIN = '"+ userLogin +"' AND EXPIRY > CURRENT_TIMESTAMP "
            + " ORDER BY EXPIRY DESC ";
    Map<String, String> params = new HashMap<>();
    
    log.debug("Executing query : "+query);
    List<UserTokenDTO> userTokenList = entityManagerService.getUserTokenDetails(query, params);
    return userTokenList.isEmpty() ? null : userTokenList.get(0);
}

When i run this API it says "java.lang.SecurityException: No security context bound to the current thread"
I feel when we are calling service method getAnonymousToken(String userLogin) it is asking for token.


(Shanur Anasari) #3

Do we need to make any changes in the “portal-security-spring.xml” configuration


(Max Gorbunkov) #5

Hi,
2 thoughts:

  1. If you don’t need any security for your endpoints, maybe you can disable it?
<security:http pattern="/rest/myapi/**" security="none"/>
  1. Check that your service method uses system authentication: https://doc.cuba-platform.com/manual-6.7/system_authentication.html

(Shanur Anasari) #7

Thanks for the reply @gorbunkov I will try to make the changes you suggested and update you back


(Shashank Singhal) #8

Hi,

I tried this in cuba version 6.9.4 but I keep getting following error:

{
    "error": "unauthorized",
    "error_description": "An Authentication object was not found in the SecurityContext"
}

Am I missing something??

Thanks


(Shanur Anasari) #9

Hi @shashanksinghal,

Which type of request you are making?
GET or POST?

Regards
Shanur


(Anjingjing) #10

Hi Max,
So for the 2 ways you mentioned, what is the difference about use case while using them?
For which kind of case, we use #1 and which case for #2?
Any security issue needs to be concerned?

If I need to develop some API which is public, for example, user self register; public get method which used in product description html, user manual,etc?


(Max Gorbunkov) #11

Hi,
That were not two cases, that were two parts of solving the problem: first, authentication for given endpoint must be disabled, and second, when some operations that require CUBA system authentication are performed in the accessed controller, then such an authentication must be performed (see the documentation link)
If your case is serving a static content (documentation, html pages and so on) then you may use DispatcherServiet for this.

  1. Create modules/web/web/website directory and add static resources there
  2. Modify your web-dispatcher-spring.xml file:
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.3.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:resources mapping="/**" location="/website/" />
    <mvc:view-controller path="/" view-name="index.html"/>
</beans>

By default dispatcher servlet is set up on http://localhost:8080/app/dispatch/, so if you access http://localhost:8080/app/dispatch/myfile.pdf you’ll get the myfile.pdf file located in the website directory.