epugh commented on code in PR #3754: URL: https://github.com/apache/solr/pull/3754#discussion_r2807535147
########## solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/auth/AuthUtils.kt: ########## @@ -0,0 +1,91 @@ +/* + * 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.solr.ui.components.auth + +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.Base64.PaddingOption +import kotlin.random.Random +import okio.ByteString +import okio.ByteString.Companion.encodeUtf8 + +/** + * Characters allowed by RFC 7636 for the code verifier + */ +internal const val CODE_VERIFIER_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" + +internal const val CODE_VERIFIER_LENGTH = 128 + +/** + * Characters to use for the state generation during OAuth flows. + */ +internal const val STATE_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +/** + * Length of the state value during OAuth flows. + */ +internal const val STATE_LENGTH = 32 + +/** + * Generates a code verifier that is used during OAuth flows. + * + * @return Code verifier that adheres to the allowed characters defined in [CODE_VERIFIER_CHARSET] + * and the required length as defined by [CODE_VERIFIER_LENGTH]. + */ +internal fun generateCodeVerifier(): String = buildString { + repeat(CODE_VERIFIER_LENGTH) { + append(CODE_VERIFIER_CHARSET[Random.nextInt(CODE_VERIFIER_CHARSET.length)]) + } +} + +/** + * Generates a code challenge that is used during OAuth flows. + * + * @param verifier Code verifier as generated by [generateCodeVerifier]. + * @return The URL-safe, Base64-encoded code challenge. + */ +internal fun generateCodeChallenge(verifier: String): String { + val sha256Bytes: ByteString = verifier.encodeUtf8().sha256() + return Base64.UrlSafe.withPadding(PaddingOption.ABSENT).encode(sha256Bytes.toByteArray()) +} + +/** + * Generates an OAuth state that is used during OAuth flows. + * + * @return State value with characters from [STATE_CHARSET] and length [STATE_LENGTH]. + */ +internal fun generateOAuthState(): String = buildString { + repeat(STATE_LENGTH) { + append(STATE_CHARSET[Random.nextInt(STATE_CHARSET.length)]) + } +} + +/** + * Retrieve the redirect URI for the OAuth flow. + * + * This URI is platform-specific, as it generates different redirect URIs based on the current + * target / origin. + * + * Note that in future scenarios we will have to support a changed location path, as the user is + * allowed to customize the base path that is right now /solr/ui/. + * + * TODO Implement the function so that it also allows overriding the callback path. This will + * allow us to customize the base path of Solr without affecting the new UI. Review Comment: In olden days you COULD deploy solr at various base paths. so /myapp_search or /solr_prod, but over time we went away from that. These days, we assume the base path is /solr or /api. Now, maybe you are suggesting that with a proxy in front, maybe it would be tools.mycompany.com/servers/prod/solr? I don't know if that would actualy work with Solr! ########## solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/auth/AuthUtils.kt: ########## @@ -0,0 +1,91 @@ +/* + * 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.solr.ui.components.auth + +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.Base64.PaddingOption +import kotlin.random.Random +import okio.ByteString +import okio.ByteString.Companion.encodeUtf8 + +/** + * Characters allowed by RFC 7636 for the code verifier + */ +internal const val CODE_VERIFIER_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" + +internal const val CODE_VERIFIER_LENGTH = 128 + +/** + * Characters to use for the state generation during OAuth flows. + */ +internal const val STATE_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +/** + * Length of the state value during OAuth flows. + */ +internal const val STATE_LENGTH = 32 + +/** + * Generates a code verifier that is used during OAuth flows. + * + * @return Code verifier that adheres to the allowed characters defined in [CODE_VERIFIER_CHARSET] + * and the required length as defined by [CODE_VERIFIER_LENGTH]. + */ +internal fun generateCodeVerifier(): String = buildString { + repeat(CODE_VERIFIER_LENGTH) { + append(CODE_VERIFIER_CHARSET[Random.nextInt(CODE_VERIFIER_CHARSET.length)]) + } +} + +/** + * Generates a code challenge that is used during OAuth flows. + * + * @param verifier Code verifier as generated by [generateCodeVerifier]. + * @return The URL-safe, Base64-encoded code challenge. + */ +internal fun generateCodeChallenge(verifier: String): String { + val sha256Bytes: ByteString = verifier.encodeUtf8().sha256() + return Base64.UrlSafe.withPadding(PaddingOption.ABSENT).encode(sha256Bytes.toByteArray()) +} + +/** + * Generates an OAuth state that is used during OAuth flows. + * + * @return State value with characters from [STATE_CHARSET] and length [STATE_LENGTH]. + */ +internal fun generateOAuthState(): String = buildString { + repeat(STATE_LENGTH) { + append(STATE_CHARSET[Random.nextInt(STATE_CHARSET.length)]) + } +} + +/** + * Retrieve the redirect URI for the OAuth flow. + * + * This URI is platform-specific, as it generates different redirect URIs based on the current + * target / origin. + * + * Note that in future scenarios we will have to support a changed location path, as the user is + * allowed to customize the base path that is right now /solr/ui/. Review Comment: why would we want to make a change to the base path? Why not just always be /solr/ui? ########## solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/start/integration/HttpStartStoreClient.kt: ########## @@ -91,11 +98,36 @@ class HttpStartStoreClient( // Split by comma, as there is the chance that headers will be merged and separated by // comma (e.g. on web target) .flatMap { header -> header.split(",") } - .map { authHeader -> + .map(String::trim) + .mapIndexed { index, authHeader -> val (scheme, params) = parseWwwAuthenticate(authHeader) when (scheme.lowercase()) { "basic", "xbasic" -> AuthMethod.BasicAuthMethod(realm = params["realm"]) Review Comment: i will say, the basic/xbasic, which isn't what this is about, i know, but it would be nice to figure out how to avoid the need for xbasic. Seems like we need to fix something solr server side. ########## solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/HttpClientUtils.kt: ########## @@ -79,3 +87,23 @@ fun getHttpClientWithCredentials( } } } + +fun getHttpClientWithBearerTokens( + accessToken: String, + refreshToken: String? = null, + url: Url = Url("http://127.0.0.1:8983/"), Review Comment: is this url supposed to be hardcoded to a localhost? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
