[ https://issues.apache.org/jira/browse/KNOX-3028?focusedWorklogId=914517&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-914517 ]
ASF GitHub Bot logged work on KNOX-3028: ---------------------------------------- Author: ASF GitHub Bot Created on: 13/Apr/24 21:01 Start Date: 13/Apr/24 21:01 Worklog Time Spent: 10m Work Description: lmccay commented on code in PR #900: URL: https://github.com/apache/knox/pull/900#discussion_r1564253699 ########## gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/OAuthResource.java: ########## @@ -0,0 +1,133 @@ +/* + * 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.knox.gateway.service.knoxtoken; + +import org.apache.knox.gateway.i18n.messages.MessagesFactory; +import org.apache.knox.gateway.util.JsonUtils; + +import javax.inject.Singleton; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +import java.time.Duration; +import java.time.format.DateTimeParseException; +import java.util.HashMap; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.MediaType.APPLICATION_XML; + +@Singleton +@Path(OAuthResource.RESOURCE_PATH) +public class OAuthResource extends TokenResource { + private static TokenServiceMessages log = MessagesFactory.get(TokenServiceMessages.class); + static final String RESOURCE_PATH = "/{serviceName:.*}/v1/{oauthSegment:(oauth|token)}{path:(/tokens)?}"; + public static final String ISSUED_TOKEN_TYPE = "issued_token_type"; + public static final String REFRESH_TOKEN = "refresh_token"; + public static final String ISSUED_TOKEN_TYPE_ACCESS_TOKEN_VALUE = "urn:ietf:params:oauth:token-type:access_token"; + + @Override + @GET + @Produces({ APPLICATION_JSON, APPLICATION_XML }) + public Response doGet() { + return super.doGet(); + } + + @Override + @POST + @Produces({ APPLICATION_JSON, APPLICATION_XML }) + public Response doPost() { + return super.doPost(); + } + + @Override + public Response getAuthenticationToken() { + + Response response = enforceClientCertIfRequired(); + if (response != null) { return response; } + + response = onlyAllowGroupsToBeAddedWhenEnabled(); + if (response != null) { return response; } + + UserContext context = buildUserContext(request); + + response = enforceTokenLimitsAsRequired(context.userName); + if (response != null) { return response; } + + TokenResponse resp = getTokenResponse(context); + // if the responseMap isn't null then the knoxtoken request was successful + // if not then there may have been an error and the underlying response + // builder will communicate those details + if (resp.responseMap != null) { + // let's get the subset of the KnoxToken Response needed for OAuth + String accessToken = resp.responseMap.accessToken; + String passcode = resp.responseMap.passcode; + long expires = (long) resp.responseMap.map.get(EXPIRES_IN); + String tokenType = (String) resp.responseMap.map.get(TOKEN_TYPE); + + // build and return the expected OAuth response + final HashMap<String, Object> map = new HashMap<>(); + map.put(ACCESS_TOKEN, accessToken); + map.put(TOKEN_TYPE, tokenType); + map.put(EXPIRES_IN, expires); + map.put(ISSUED_TOKEN_TYPE, ISSUED_TOKEN_TYPE_ACCESS_TOKEN_VALUE); + // let's use the passcode as the refresh token + map.put(REFRESH_TOKEN, passcode); + String jsonResponse = JsonUtils.renderAsJsonString(map); + return resp.responseBuilder.entity(jsonResponse).build(); + } + // there was an error if we got here - let's surface it appropriately + // TODO: LJM we may need to translate certain errors into OAuth error messages + if (resp.responseStr != null) { + return resp.responseBuilder.entity(resp.responseStr).build(); + } + else { + return resp.responseBuilder.build(); + } + } + + @Override + protected long getExpiry() { + long secs = tokenTTL/1000; + + String lifetimeStr = request.getParameter(LIFESPAN); + if (lifetimeStr == null || lifetimeStr.isEmpty()) { + if (tokenTTL == -1) { + return -1; + } + } + else { Review Comment: Resolving to be consistent with the rest of the class. Issue Time Tracking ------------------- Worklog Id: (was: 914517) Time Spent: 2h 20m (was: 2h 10m) > KnoxToken extension for OAuth Token Flows > ----------------------------------------- > > Key: KNOX-3028 > URL: https://issues.apache.org/jira/browse/KNOX-3028 > Project: Apache Knox > Issue Type: Bug > Components: JWT > Reporter: Larry McCay > Assignee: Larry McCay > Priority: Major > Fix For: 2.1.0 > > Time Spent: 2h 20m > Remaining Estimate: 0h > > This change will extend the existing TokenResource for KNOXTOKEN service to > include OAuth specifics such as expected URL, error messages and flows to > support Token Exchange Flow and Token Refresh. > This is being driven by a specific need to proxy access to the Iceberg REST > Catalog API. In this specific usecase, we need to intercept the use of the > following endpoint URLs and serve the token exchange flow for the > authenticating user. > {code} > /v1/oauth/tokens > {code} > Details for these requirements can be found in the openapi description for > the catalog API [1]. > In addition to this usecase, we should add generic support for the token > exchange flow with more generic URL that better aligns with what others use. > {code} > /oauth/v1/token > {code} > We will support the use of the "oauth" service name within the existing > KNOXTOKEN service with an extension of the TokenResource which adapts the > existing KNOXTOKEN behavior to the expectations of clients on OAuth responses. > In order to support both URLs, the deployment contributor will need to > register a url pattern for each usecase and the resource path within the > jersey service will need to accommodate the dynamic nature of the Iceberg > REST Catalog API which will add the catalog API service name as well. > {code} > /icecli/v1/oauth/tokens/ > {code} > Where "icecli" may be some configurable service name and need to match to the > incoming URL. > We will wildcard that by making it a regex matched path param. > We will also need to accommodate a first-class Knox pattern and service name > of "oauth" and only allow "token" or "oauth" after the v1 with the remaining > path fragment being optional for the iceberg specific "tokens". > Not pretty but it will work. > 1. > https://github.com/apache/iceberg/blob/main/open-api/rest-catalog-open-api.yaml -- This message was sent by Atlassian Jira (v8.20.10#820010)