From 636beeb7f3df0578755d889d0e11fb3c0b38411f Mon Sep 17 00:00:00 2001 From: TanelOrumaa Date: Thu, 11 Nov 2021 21:47:27 +0200 Subject: [PATCH] MOB-42 Fixed token authentication issues (wrong library version, cache getting recreated every request, origin in wrong form) --- .../mobileauthapp/AuthFragment.kt | 2 +- .../mobileauthapp/HomeFragment.kt | 9 ++++++++- .../mobileauthapp/ResultFragment.kt | 2 +- .../mobileauthapp/auth/Authenticator.kt | 6 +++--- .../mobileauthapp/model/ParametersViewModel.kt | 7 +++++++ demoBackend/pom.xml | 5 +++++ .../config/ApplicationConfiguration.kt | 2 +- .../config/ValidationConfiguration.kt | 17 ++++++++++++++++- .../AuthTokenDTOAuthenticationProvider.kt | 12 +++++++----- .../demobackend/web/SignatureController.kt | 2 +- .../web/rest/AuthenticationController.kt | 2 +- .../demobackend/web/rest/ChallengeController.kt | 3 +++ .../src/main/resources/static/css/main.css | 4 ++++ .../src/main/resources/static/js/main.js | 8 ++++---- .../src/main/resources/templates/index.html | 4 ++-- 15 files changed, 64 insertions(+), 21 deletions(-) diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt index ed6de75..3adfdf4 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt @@ -90,7 +90,7 @@ class AuthFragment : Fragment() { if (args.auth) { val jws = Authenticator(comms).authenticate( intentParameters.challenge, - intentParameters.authUrl, + intentParameters.origin, viewModel.userPin ) intentParameters.setToken(jws) diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt index f0b60e6..dff550a 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt @@ -14,6 +14,7 @@ import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentHomeBinding import com.tarkvaraprojekt.mobileauthapp.model.ParametersViewModel import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel import java.lang.Exception +import java.net.URLDecoder /** * HomeFragment is only shown to the user when then the user launches the application. When the application @@ -30,6 +31,7 @@ class HomeFragment : Fragment() { private var binding: FragmentHomeBinding? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -56,11 +58,16 @@ class HomeFragment : Fragment() { // We use !! because we want an exception when something is not right. intentParams.setChallenge(requireActivity().intent.getStringExtra("challenge")!!) intentParams.setAuthUrl(requireActivity().intent.getStringExtra("authUrl")!!) + intentParams.setOrigin(requireActivity().intent.getStringExtra("originUrl")!!) } else { //Website // Currently the test website won't send the authUrl parameter //Log.i("intentDebugging", requireActivity().intent.data.toString()) - intentParams.setChallenge(requireActivity().intent.data!!.getQueryParameter("challenge")!!) + var challenge = requireActivity().intent.data!!.getQueryParameter("challenge")!! + // TODO: Since due to encoding plus gets converted to space, temporary solution is to replace it back. + challenge = challenge.replace(" ", "+") + intentParams.setChallenge(challenge) intentParams.setAuthUrl(requireActivity().intent.data!!.getQueryParameter("authUrl")!!) + intentParams.setOrigin(requireActivity().intent.data!!.getQueryParameter("originUrl")!!) } } catch (e: Exception) { // There was a problem with parameters, which means that authentication is not possible. diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt index 6eddd05..98e9cac 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt @@ -67,7 +67,7 @@ class ResultFragment : Fragment() { Ion.getDefault(activity).getConscryptMiddleware().enable(false) Ion.with(activity) - .load("https://6bb0-85-253-195-252.ngrok.io/auth/authentication") + .load(paramsModel.origin + paramsModel.authUrl) .setJsonObjectBody(json) .asJsonObject() .setCallback { e, result -> diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/Authenticator.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/Authenticator.kt index 383ad68..023602b 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/Authenticator.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/Authenticator.kt @@ -8,7 +8,7 @@ import java.security.MessageDigest import java.time.LocalDateTime import java.time.ZoneOffset -class Authenticator(val comms : Comms) { +class Authenticator(val comms: Comms) { val type = "JWT" val algorithm = "ES384" @@ -36,7 +36,7 @@ class Authenticator(val comms : Comms) { // Get header and claims. val header = """{"typ":"$type","alg":"$algorithm","x5c":["$base64cert"]}""" val claims = - """{"iat":"$epoch","exp":"$exp","aud":"$originUrl","iss":"$iss","sub":"$sub","nonce":"$challenge","cnf":{"tbh":""}}""" + """{"iat":"$epoch","exp":"$exp","aud":["$originUrl"],"iss":"$iss","sub":"$sub","nonce":"$challenge","cnf":{"tbh":""}}""" val jwt = base64Encode(header.toByteArray(Charsets.UTF_8)) + "." + base64Encode( claims.toByteArray(Charsets.UTF_8) @@ -51,7 +51,7 @@ class Authenticator(val comms : Comms) { return jwt + "." + base64Encode(signed) } - fun base64Encode(bytes: ByteArray) : String? { + fun base64Encode(bytes: ByteArray): String? { val encoded = java.util.Base64.getUrlEncoder().encodeToString(bytes) return encoded.replace("=", "") } diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/model/ParametersViewModel.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/model/ParametersViewModel.kt index 0a76f1d..dbac034 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/model/ParametersViewModel.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/model/ParametersViewModel.kt @@ -13,6 +13,9 @@ class ParametersViewModel: ViewModel() { private var _token: String = "" val token get() = _token + private var _origin: String = "" + val origin get() = _origin + fun setChallenge(newChallenge: String) { _challenge = newChallenge } @@ -24,4 +27,8 @@ class ParametersViewModel: ViewModel() { fun setToken(newToken: String) { _token = newToken } + + fun setOrigin(newOrigin: String) { + _origin = newOrigin + } } \ No newline at end of file diff --git a/demoBackend/pom.xml b/demoBackend/pom.xml index bd4ba2a..8b1f7a3 100644 --- a/demoBackend/pom.xml +++ b/demoBackend/pom.xml @@ -42,6 +42,11 @@ spring-boot-starter-test test + + com.squareup.okhttp3 + okhttp + 4.9.0 + org.webeid.security authtoken-validation diff --git a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ApplicationConfiguration.kt b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ApplicationConfiguration.kt index d025eed..abee1f8 100644 --- a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ApplicationConfiguration.kt +++ b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ApplicationConfiguration.kt @@ -10,7 +10,7 @@ class ApplicationConfiguration { // Endpoint for authentication val AUTHENTICATION_ENDPOINT_URL = "/auth/authentication" // URL for application. Use ngrok for HTTPS (or a tool of your own choice) and put the HTTPS link here. - val WEBSITE_ORIGIN_URL = "https://6bb0-85-253-195-252.ngrok.io" + val WEBSITE_ORIGIN_URL = "https://2c2c-85-253-195-252.ngrok.io" } } \ No newline at end of file diff --git a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ValidationConfiguration.kt b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ValidationConfiguration.kt index 237fcdd..3bdefc4 100644 --- a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ValidationConfiguration.kt +++ b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/config/ValidationConfiguration.kt @@ -1,6 +1,8 @@ package com.tarkvaratehnika.demobackend.config import com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.io.support.PathMatchingResourcePatternResolver @@ -28,14 +30,25 @@ import javax.cache.configuration.MutableConfiguration import javax.cache.expiry.CreatedExpiryPolicy import javax.cache.expiry.Duration +import javax.cache.configuration.FactoryBuilder.factoryOf + @Configuration class ValidationConfiguration { + private val LOG: Logger = LoggerFactory.getLogger(ValidationConfiguration::class.java) + private val NONCE_TTL_MINUTES: Long = 5 private val CACHE_NAME = "nonceCache" private val CERTS_RESOURCE_PATH = "/certs/" private val TRUSTED_CERTIFICATES_JKS = "trusted_certificates.jks" private val TRUSTSTORE_PASSWORD = "changeit" + companion object { + const val ROLE_USER : String = "ROLE_USER" + } + + init { + LOG.warn("Creating new ValidationConfiguration.") + } @Bean fun cacheManager(): CacheManager { @@ -47,7 +60,9 @@ class ValidationConfiguration { val cacheManager: CacheManager = cacheManager() var cache = cacheManager.getCache(CACHE_NAME) + if (cache == null) { + LOG.warn("Creating new cache.") cache = createNonceCache(cacheManager) } return cache @@ -65,7 +80,7 @@ class ValidationConfiguration { val cacheConfig: CompleteConfiguration = MutableConfiguration() .setTypes(String::class.java, ZonedDateTime::class.java) .setExpiryPolicyFactory( - FactoryBuilder.factoryOf( + factoryOf( CreatedExpiryPolicy( Duration( TimeUnit.MINUTES, diff --git a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/security/AuthTokenDTOAuthenticationProvider.kt b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/security/AuthTokenDTOAuthenticationProvider.kt index 6bdeab7..122eb1b 100644 --- a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/security/AuthTokenDTOAuthenticationProvider.kt +++ b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/security/AuthTokenDTOAuthenticationProvider.kt @@ -23,6 +23,9 @@ package com.tarkvaratehnika.demobackend.security import com.tarkvaratehnika.demobackend.config.ValidationConfiguration +import com.tarkvaratehnika.demobackend.config.ValidationConfiguration.Companion.ROLE_USER +import com.tarkvaratehnika.demobackend.web.rest.AuthenticationController +import org.slf4j.LoggerFactory import org.springframework.security.authentication.AuthenticationServiceException import org.springframework.security.core.Authentication import org.springframework.security.core.AuthenticationException @@ -37,11 +40,11 @@ import java.security.cert.X509Certificate @Component -class AuthTokenDTOAuthenticationProvider { +object AuthTokenDTOAuthenticationProvider { + + private val LOG = LoggerFactory.getLogger(AuthTokenDTOAuthenticationProvider::class.java) + - companion object { - const val ROLE_USER : String = "ROLE_USER" - } private val USER_ROLE: GrantedAuthority = SimpleGrantedAuthority(ROLE_USER) @@ -52,7 +55,6 @@ class AuthTokenDTOAuthenticationProvider { val authentication = auth as PreAuthenticatedAuthenticationToken val token = (authentication.credentials as AuthTokenDTO).token val challenge = (authentication.credentials as AuthTokenDTO).challenge - val authorities = arrayListOf() authorities.add(USER_ROLE) diff --git a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/SignatureController.kt b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/SignatureController.kt index bcc12ad..d526fec 100644 --- a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/SignatureController.kt +++ b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/SignatureController.kt @@ -1,6 +1,6 @@ package com.tarkvaratehnika.demobackend.web -import com.tarkvaratehnika.demobackend.security.AuthTokenDTOAuthenticationProvider.Companion.ROLE_USER +import com.tarkvaratehnika.demobackend.config.ValidationConfiguration.Companion.ROLE_USER import org.springframework.security.access.prepost.PreAuthorize import org.springframework.stereotype.Controller import org.springframework.ui.Model diff --git a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/AuthenticationController.kt b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/AuthenticationController.kt index 68a3f5b..6414441 100644 --- a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/AuthenticationController.kt +++ b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/AuthenticationController.kt @@ -26,7 +26,7 @@ class AuthenticationController { val auth = PreAuthenticatedAuthenticationToken(null, authToken) // Return authentication object if success. - return AuthTokenDTOAuthenticationProvider().authenticate(auth) + return AuthTokenDTOAuthenticationProvider.authenticate(auth) } @GetMapping("authentication", produces = [MediaType.APPLICATION_JSON_VALUE]) diff --git a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/ChallengeController.kt b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/ChallengeController.kt index ae29d63..7333c9d 100644 --- a/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/ChallengeController.kt +++ b/demoBackend/src/main/kotlin/com/tarkvaratehnika/demobackend/web/rest/ChallengeController.kt @@ -24,6 +24,7 @@ package com.tarkvaratehnika.demobackend.web.rest import com.tarkvaratehnika.demobackend.dto.ChallengeDto import com.tarkvaratehnika.demobackend.security.WebEidAuthentication +import org.slf4j.LoggerFactory import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -33,10 +34,12 @@ import org.webeid.security.nonce.NonceGenerator @RequestMapping("auth") class ChallengeController (val nonceGenerator: NonceGenerator) { + private val LOG = LoggerFactory.getLogger(ChallengeController::class.java) @GetMapping("challenge") fun challenge(): ChallengeDto { val challengeDto = ChallengeDto(nonceGenerator.generateAndStoreNonce()) + LOG.warn(challengeDto.nonce) // WebEidAuthentication.addAuth(challengeDto.nonce) // For testing. return challengeDto } diff --git a/demoBackend/src/main/resources/static/css/main.css b/demoBackend/src/main/resources/static/css/main.css index b28c55e..31f3ebe 100644 --- a/demoBackend/src/main/resources/static/css/main.css +++ b/demoBackend/src/main/resources/static/css/main.css @@ -1,3 +1,7 @@ +html { + font-size: 4vw; +} + .cont { display: grid; width: 80%; diff --git a/demoBackend/src/main/resources/static/js/main.js b/demoBackend/src/main/resources/static/js/main.js index f38d255..46b607a 100644 --- a/demoBackend/src/main/resources/static/js/main.js +++ b/demoBackend/src/main/resources/static/js/main.js @@ -11,7 +11,7 @@ function launchAuthApp(action) { httpGetAsync(originUrl + challengeUrl, (body) => { let data = JSON.parse(body); let challenge = data.nonce; - let intent = createParametrizedIntentUrl(challenge, action); // TODO: Error handling. + let intent = createParametrizedIntentUrl(challenge, action, originUrl); // TODO: Error handling. console.log(intent); window.location.href = intent; pollForAuth(POLLING_INTERVAL, challenge); @@ -20,8 +20,8 @@ function launchAuthApp(action) { function pollForAuth(timeout, challenge) { console.log("Polling for auth"); - let requestUrl = originUrl + authenticationRequestUrl + "?challenge=" + challenge; - + let encodedChallenge = encodeURIComponent(challenge); + let requestUrl = originUrl + authenticationRequestUrl + "?challenge=" + encodedChallenge; let counter = 0; let timer = setInterval(() => { // Fetch authentication object. @@ -48,7 +48,7 @@ function createParametrizedIntentUrl(challenge, action) { else if (challenge == null) { console.error("Challenge missing, can't authenticate without it.") } else { - return intentUrl + "?" + "action=" + action + "&challenge=" + challenge + "&authUrl=" + originUrl + authenticationRequestUrl; + return intentUrl + "?" + "action=" + action + "&challenge=" + encodeURIComponent(challenge) + "&authUrl=" + authenticationRequestUrl + "&originUrl=" + originUrl; } } diff --git a/demoBackend/src/main/resources/templates/index.html b/demoBackend/src/main/resources/templates/index.html index e6ae490..a436fea 100644 --- a/demoBackend/src/main/resources/templates/index.html +++ b/demoBackend/src/main/resources/templates/index.html @@ -21,7 +21,7 @@
@@ -29,7 +29,7 @@ website using your ID card by using the button below.
Make sure you've installed the authentication app from: GitHub
- +