diff --git a/service/fling/src/main/java/net/friedl/fling/service/AuthenticationService.java b/service/fling/src/main/java/net/friedl/fling/service/AuthenticationService.java
index e15fb73..2617716 100644
--- a/service/fling/src/main/java/net/friedl/fling/service/AuthenticationService.java
+++ b/service/fling/src/main/java/net/friedl/fling/service/AuthenticationService.java
@@ -15,12 +15,14 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import net.friedl.fling.model.dto.AdminAuthDto;
+import net.friedl.fling.model.dto.FlingDto;
import net.friedl.fling.model.dto.UserAuthDto;
import net.friedl.fling.persistence.entities.FlingEntity;
import net.friedl.fling.persistence.entities.TokenEntity;
@@ -84,10 +86,14 @@ public class AuthenticationService {
throw new EntityNotFoundException("No entity for shareId=" + userAuth.getShareId());
}
- String providedAuthCodeHash = passwordEncoder.encode(userAuth.getAuthCode());
+ String providedAuthCode = userAuth.getAuthCode();
String actualAuthCodeHash = flingEntity.getAuthCode();
+
+ Boolean isProtected = StringUtils.hasText(actualAuthCodeHash);
- if (!actualAuthCodeHash.equals(providedAuthCodeHash)) {
+ if(!isProtected) log.debug("No protection set for fling [.shareId={}]");
+
+ if (isProtected && !passwordEncoder.matches(providedAuthCode, actualAuthCodeHash)) {
log.debug("Authentication failed for fling [.shareId={}]", userAuth.getShareId());
return Optional.empty();
}
@@ -96,6 +102,7 @@ public class AuthenticationService {
return Optional.of(
getJwtBuilder()
.setSubject("user")
+ .claim("shareId", flingEntity.getShareId())
.claim("id", flingEntity.getId())
.compact());
diff --git a/service/fling/src/test/java/net/friedl/fling/service/AuthenticationServiceTest.java b/service/fling/src/test/java/net/friedl/fling/service/AuthenticationServiceTest.java
index e829625..4413353 100644
--- a/service/fling/src/test/java/net/friedl/fling/service/AuthenticationServiceTest.java
+++ b/service/fling/src/test/java/net/friedl/fling/service/AuthenticationServiceTest.java
@@ -118,6 +118,16 @@ public class AuthenticationServiceTest {
assertThat(authenticationService.authenticate(userAuthDto), equalTo(Optional.empty()));
}
+ @Test
+ public void authenticate_authCodeEmpty_ok() {
+ FlingEntity flingEntity = new FlingEntity();
+ UserAuthDto userAuthDto = new UserAuthDto("shareId", "");
+
+ when(flingRepository.findByShareId(any(String.class))).thenReturn(flingEntity);
+
+ assertThat(authenticationService.authenticate(userAuthDto), not(equalTo(Optional.empty())));
+ }
+
@Test
public void authenticate_authCodeEquals_ok() {
FlingEntity flingEntity = new FlingEntity();
@@ -130,6 +140,7 @@ public class AuthenticationServiceTest {
when(flingRepository.findByShareId(any(String.class))).thenReturn(flingEntity);
when(passwordEncoder.encode(any(String.class))).thenReturn("authCodeHash");
+ when(passwordEncoder.matches("authCode", "authCodeHash")).thenReturn(true);
assertThat(authenticationService.authenticate(userAuthDto), not(equalTo(Optional.empty())));
}
diff --git a/web/fling/src/App.jsx b/web/fling/src/App.jsx
index 4c9f970..942dcab 100644
--- a/web/fling/src/App.jsx
+++ b/web/fling/src/App.jsx
@@ -87,7 +87,7 @@ function UserRoute({ children, ...rest }) {
let authorized =
jwt.hasSubject("admin")
- || ( jwt.hasSubject("user") && jwt.hasClaim("id", state['shareId']) );
+ || ( jwt.hasSubject("user") && jwt.hasClaim("shareId", state['shareId']) );
if (authorized) { return children; }
else { return ; }
diff --git a/web/fling/src/components/user/Error.jsx b/web/fling/src/components/user/Error.jsx
deleted file mode 100644
index be4d4c4..0000000
--- a/web/fling/src/components/user/Error.jsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import React, {useState} from 'react';
-import classNames from 'classnames';
-
-import log from 'loglevel';
-
-export default (props) => {
- function renderError() {
- return (
-
-
-
Ooops!
-
- { props.errors.map( (err, idx) => ) }
-
-
- );
- }
-
- return (
- <>
- { props.errors.length > 0 && !props.below ? renderError() : "" }
- { props.children }
- { props.errors.length > 0 && props.below ? renderError() : "" }
- >
- );
-}
diff --git a/web/fling/src/components/user/FlingUser.jsx b/web/fling/src/components/user/FlingUser.jsx
index ec13db7..b76a37f 100644
--- a/web/fling/src/components/user/FlingUser.jsx
+++ b/web/fling/src/components/user/FlingUser.jsx
@@ -1,26 +1,27 @@
-import React, {useState, useEffect} from 'react';
+import React, { useState, useEffect } from 'react';
-import {useParams} from 'react-router-dom';
+import { useParams } from 'react-router-dom';
-import {flingClient} from '../../util/flingclient';
+import { FlingClient } from '../../util/fc';
import DirectDownload from './DirectDownload';
import FlingUserList from './FlingUserList';
export default function FlingUser() {
- let { shareId } = useParams();
- let [fling, setFling] = useState({});
+ let { shareId } = useParams();
+ let [fling, setFling] = useState({});
- useEffect(() => {
- flingClient.getFlingByShareId(shareId)
- .then(f => setFling(f));
- }, [shareId]);
+ useEffect(() => {
+ let flingClient = new FlingClient();
+ flingClient.getFlingByShareId(shareId)
+ .then(f => setFling(f));
+ }, [shareId]);
- return(
-
- {fling.sharing && fling.sharing.directDownload
- ?
- : }
-
- );
+ return (
+
+ {fling.sharing && fling.sharing.directDownload
+ ?
+ : }
+
+ );
}
diff --git a/web/fling/src/components/user/Unlock.jsx b/web/fling/src/components/user/Unlock.jsx
index 3dec25c..799be63 100644
--- a/web/fling/src/components/user/Unlock.jsx
+++ b/web/fling/src/components/user/Unlock.jsx
@@ -1,61 +1,60 @@
import log from 'loglevel';
-import React, {useState, useEffect} from 'react';
-import {useHistory, useLocation} from 'react-router-dom';
+import React, { useState, useEffect } from 'react';
+import { useHistory, useLocation } from 'react-router-dom';
-import request, {setAuth} from '../../util/request';
+import { AuthClient, fc } from '../../util/fc';
export default function Unlock() {
- const [authCode, setAuthCode] = useState("");
- const history = useHistory();
- const location = useLocation();
- const { from, shareId } = location.state || { from: { pathname: "/admin" }, shareId: "" };
+ const [authCode, setAuthCode] = useState("");
+ const history = useHistory();
+ const location = useLocation();
+ const { from, shareId } = location.state || { from: { pathname: "/admin" }, shareId: "" };
- useEffect(() => setAuth(null), []);
+ useEffect(() => {
+ let authClient = new AuthClient();
+ let userAuth = new fc.UserAuth(location.state.shareId, "")
- useEffect(() => {
- request.post("/auth/user", {"shareId": location.state.shareId})
- .then(response => {
- log.info("Fling is not protected. Logged in successfully.");
- setAuth(response.data);
- history.replace(location.state.from);
- })
- .catch(err => {/* ignored */});
- }, [location, history]);
+ authClient.authenticateUser({ 'userAuth': userAuth })
+ .then(response => {
+ log.info("Fling is not protected. Logged in successfully.");
+ sessionStorage.setItem('token', response);
+ history.replace(location.state.from);
+ }).catch(error => {
+ log.info("Fling protected. Could not unlock without code.")
+ });
+ }, [location, history]);
- return (
-
-
-
-
This Fling is locked.
-
-
-
+ return (
+
+
+
+
This Fling is locked.
- );
+
+
+
+ );
- function handleSubmit(ev) {
- ev.preventDefault();
+ function handleSubmit(ev) {
+ ev.preventDefault();
+ let authClient = new AuthClient();
+ let userAuth = new fc.UserAuth(shareId, authCode)
- request.post("/auth/user", {"shareId": shareId, "code": authCode})
- .then(response => {
- log.info("Logged in successfully");
- setAuth(response.data);
- history.replace(from);
- })
- .catch(error => {
- log.error(error);
- });
- };
-
- function handleChange(ev) {
- let val = ev.target.value;
- setAuthCode(val);
- };
+ authClient.authenticateUser({ 'userAuth': userAuth })
+ .then(response => {
+ log.info("Logged in successfully");
+ sessionStorage.setItem('token', response);
+ history.replace(from);
+ }).catch(error => {
+ log.error(error);
+ });
+ };
}