/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.hadoop.hdfs.web.oauth2; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.util.Timer; import org.apache.http.HttpStatus; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; import org.mockserver.client.server.MockServerClient; import org.mockserver.integration.ClientAndServer; import org.mockserver.model.Header; import org.mockserver.model.HttpRequest; import org.mockserver.model.HttpResponse; import org.mockserver.model.Parameter; import org.mockserver.model.ParameterBody; import java.io.IOException; import java.util.Map; import java.util.TreeMap; import static org.apache.hadoop.hdfs.DFSConfigKeys.OAUTH_CLIENT_ID_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.OAUTH_REFRESH_URL_KEY; import static org.apache.hadoop.hdfs.web.oauth2.ConfRefreshTokenBasedAccessTokenProvider.OAUTH_REFRESH_TOKEN_EXPIRES_KEY; import static org.apache.hadoop.hdfs.web.oauth2.ConfRefreshTokenBasedAccessTokenProvider.OAUTH_REFRESH_TOKEN_KEY; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.ACCESS_TOKEN; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.BEARER; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.CLIENT_ID; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.EXPIRES_IN; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.GRANT_TYPE; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.REFRESH_TOKEN; import static org.apache.hadoop.hdfs.web.oauth2.OAuth2Constants.TOKEN_TYPE; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockserver.integration.ClientAndServer.startClientAndServer; import static org.mockserver.matchers.Times.exactly; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; public class TestRefreshTokenTimeBasedTokenRefresher { public final static Header CONTENT_TYPE_APPLICATION_JSON = new Header("Content-Type", "application/json"); public Configuration buildConf(String refreshToken, String tokenExpires, String clientId, String refreshURL) { // Configurations are simple enough that it's not worth mocking them out. Configuration conf = new Configuration(); conf.set(OAUTH_REFRESH_TOKEN_KEY, refreshToken); conf.set(OAUTH_REFRESH_TOKEN_EXPIRES_KEY, tokenExpires); conf.set(OAUTH_CLIENT_ID_KEY, clientId); conf.set(OAUTH_REFRESH_URL_KEY, refreshURL); return conf; } @Test public void refreshUrlIsCorrect() throws IOException { final int PORT = 7552; final String REFRESH_ADDRESS = "http://localhost:" + PORT + "/refresh"; long tokenExpires = 0; Configuration conf = buildConf("refresh token key", Long.toString(tokenExpires), "joebob", REFRESH_ADDRESS); Timer mockTimer = mock(Timer.class); when(mockTimer.now()).thenReturn(tokenExpires + 1000l); AccessTokenProvider tokenProvider = new ConfRefreshTokenBasedAccessTokenProvider(mockTimer); tokenProvider.setConf(conf); // Build mock server to receive refresh request ClientAndServer mockServer = startClientAndServer(PORT); HttpRequest expectedRequest = request() .withMethod("POST") .withPath("/refresh") // Note, OkHttp does not sort the param values, so we need to // do it ourselves via the ordering provided to ParameterBody... .withBody( ParameterBody.params( Parameter.param(CLIENT_ID, "joebob"), Parameter.param(GRANT_TYPE, REFRESH_TOKEN), Parameter.param(REFRESH_TOKEN, "refresh token key"))); MockServerClient mockServerClient = new MockServerClient("localhost", PORT); // https://tools.ietf.org/html/rfc6749#section-5.1 Map<String, Object> map = new TreeMap<>(); map.put(EXPIRES_IN, "0987654321"); map.put(TOKEN_TYPE, BEARER); map.put(ACCESS_TOKEN, "new access token"); ObjectMapper mapper = new ObjectMapper(); HttpResponse resp = response() .withStatusCode(HttpStatus.SC_OK) .withHeaders( CONTENT_TYPE_APPLICATION_JSON ) .withBody(mapper.writeValueAsString(map)); mockServerClient .when(expectedRequest, exactly(1)) .respond(resp); assertEquals("new access token", tokenProvider.getAccessToken()); mockServerClient.verify(expectedRequest); mockServerClient.clear(expectedRequest); mockServer.stop(); } }