无法在同一个应用程序中实施Stormpath表单登录/身份验证以及REST oAuth身份验证

时间:2015-11-09 09:20:33

标签: java rest oauth stormpath

我们正在使用stormpath with Java&还试图在同一个应用程序中将表单Login和REST API身份验证结合起来。

我已按照此处所述设置了stormpath servlet插件https://docs.stormpath.com/java/servlet-plugin/quickstart.html ...这非常正常。

现在,在同一个应用程序中,我们有API,我已经使用stormpath实现了oAuth身份验证,请参阅此处http://docs.stormpath.com/guides/api-key-management/

第一次访问令牌请求可以通过在请求标头中发送Basic Base64(keyId:keySecret)并在正文中发送grant_type = client_credentials来正常工作。访问令牌正在很好地返回。但是,尝试使用标头Bearer <the-obtained-access-token>验证后续请求之前甚至没有命中应用程序 返回以下json错误消息...

{
    "error": "invalid_client",
    "error_description": "access_token is invalid."
}

这很令人困惑,因为我在整个应用程序中设置了断点,我很确定在stormpath启动并返回此错误之前,API请求没有到达应用程序中的任何位置。即使stormpath在进入REST接口之前以某种方式拦截了请求,这条消息对我来说没有任何意义,因为我肯定使用从第一次调用获得的有效访问令牌进行后续API调用以获取访问权限 - 令牌。

我已经没想到为什么会发生这种情况,但我怀疑它可能与stormpath配置有关,特别是与组合 用于Web视图的登录/身份验证和用于REST端点的oAuth身份验证。话虽如此,这就是我的stormpath.properties的样子。希望这可以帮助指出我可能做错的任何事情。

stormpath.application.href=https://api.stormpath.com/v1/applications/[app-id]
stormpath.web.filters.authr=com.app.security.AuthorizationFilter
stormpath.web.request.event.listener = com.app.security.AuthenticationListener

stormpath.web.uris./resources/**=anon
stormpath.web.uris./assets/**=anon
stormpath.web.uris./v1.0/**=anon
stormpath.web.uris./** = authc,authr
stormpath.web.uris./**/**=authc,authr

对此的帮助将受到高度赞赏。

2 个答案:

答案 0 :(得分:2)

问题可能与不正确的请求有关。

您是否可以在应用中尝试此代码?:

 private boolean verify(String accessToken) throws OauthAuthenticationException {
     HttpRequest request = createRequestForOauth2AuthenticatedOperation(accessToken);
     AccessTokenResult result = Applications.oauthRequestAuthenticator(application)
        .authenticate(request);
     System.out.println(result.getAccount().getEmail() + " was successfully verified, you can allow your protect operation to continue");
     return true;
 }

 private HttpRequest createRequestForOauth2AuthenticatedOperation(String token) {
     try {
         Map<String, String[]> headers = new LinkedHashMap<String, String[]>();
         headers.put("Accept", new String[]{"application/json"});
         headers.put("Authorization", new String[]{"Bearer " + token});
         HttpRequest request = HttpRequests.method(HttpMethod.GET)
             .headers(headers)
             .build();
         return request;
     } catch (Exception e) {
         e.printStackTrace();
         return null;
     }
 }

答案 1 :(得分:1)

我准备了一个示例,演示了oauth令牌创建以及使用访问令牌对受保护页面的授权访问。

它构建了Stormpath SDK中的servlet示例。回购可以在这里找到:https://github.com/stormpath/stormpath-java-oauth-servlet-sample

它演示了运行servlet应用程序并使用带外程序获取并使用oauth令牌来访问受保护资源。

oauth部分的核心在TokenAuthTest.java

public class TokenAuthTest {
    public static void main(String[] args) throws Exception {

        String command = System.getProperty("command");

        if (command == null || !("getToken".equals(command) || "getPage".equals(command))) {
            System.err.println("Must supply a command:");
            System.err.println("\t-Dcommand=getToken OR");
            System.err.println("\t-Dcommand=getPage OR");
            System.exit(1);
        }

        if ("getToken".equals(command)) {
            getToken();
        } else {
            getPage();
        }
    }

    private static final String APP_URL = "http://localhost:8080";
    private static final String OAUTH_URI = "/oauth/token";
    private static final String PROTECTED_URI = "/dashboard";

    private static void getToken() throws Exception {
        String username = System.getProperty("username");
        String password = System.getProperty("password");

        if (username == null || password == null) {
            System.err.println("Must supply -Dusername=<username> -Dpassword=<password> on the command line");
            System.exit(1);
        }

        PostMethod method = new PostMethod(APP_URL + OAUTH_URI);

        method.setRequestHeader("Origin", APP_URL);
        method.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        method.addParameter("grant_type", "password");
        method.addParameter("username", username);
        method.addParameter("password", password);

        HttpClient client = new HttpClient();
        client.executeMethod(method);

        BufferedReader br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
        String readLine;
        while(((readLine = br.readLine()) != null)) {
            System.out.println(readLine);
        }
    }

    private static void getPage() throws Exception {
        String token = System.getProperty("token");

        if (token == null) {
            System.err.println("Must supply -Dtoken=<access token> on the command line");
            System.exit(1);
        }

        GetMethod method = new GetMethod(APP_URL + PROTECTED_URI);
        HttpClient client = new HttpClient();

        System.out.println("Attempting to retrieve " + PROTECTED_URI + " without token...");

        int returnCode = client.executeMethod(method);
        System.out.println("return code: " + returnCode);

        System.out.println();

        System.out.println("Attempting to retrieve " + PROTECTED_URI + " with token...");

        method.addRequestHeader("Authorization", "Bearer " + token);
        returnCode = client.executeMethod(method);
        System.out.println("return code: " + returnCode);
    }
}