Возникли проблемы при реализации формы Stormpath для входа в систему / аутентификации вместе с аутентификацией REST oAuth в том же приложении
Мы используем Stormpath с Java, а также пытаемся объединить форму Login с аутентификацией REST API в том же приложении.
Я настроил плагин сервлета Stormpath, как описано здесь https://docs.stormpath.com/java/servlet-plugin/quickstart.html... Это работает очень хорошо.
Теперь в том же приложении у нас есть API, в которых я реализовал аутентификацию oAuth с помощью stormpath, см. Здесь 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."
}
Это сбивает с толку, потому что я установил точки останова по всему приложению, и я почти уверен, что запрос API не попадает нигде в приложении, пока не начнется stormpath и вернет эту ошибку. И даже если stormpath каким-то образом перехватывает запрос перед тем, как попасть в интерфейс REST, это сообщение не имеет для меня никакого смысла, потому что я, безусловно, выполняю последующие вызовы API с действительным токеном доступа, полученным из первого вызова для получения доступа. маркер.
У меня закончились идеи, почему это может происходить, но я подозреваю, что это может иметь какое-то отношение к конфигурации Stormpath, особенно с комбинацией формы Login/Authentication для веб-представлений и oAuth Athentication для конечных точек REST. С учетом вышесказанного, вот как выглядит мой 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 ответа
Проблема может быть связана с неправильным запросом.
Можно ли попробовать этот код в своем приложении?:
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;
}
}
Я подготовил пример, который демонстрирует создание oauth-токена, а также авторизованный доступ к защищенным страницам с использованием токенов доступа.
Он построен на примере сервлета в Stormpath SDK. Репо можно найти здесь: https://github.com/stormpath/stormpath-java-oauth-servlet-sample
Он демонстрирует запуск приложения сервлета и наличие внеполосной программы для получения и использования маркеров 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);
}
}