diff --git a/Birdmap/Birdmap.csproj b/Birdmap/Birdmap.csproj
index 0938106..6754175 100644
--- a/Birdmap/Birdmap.csproj
+++ b/Birdmap/Birdmap.csproj
@@ -26,7 +26,10 @@
+
+
+
diff --git a/Birdmap/ClientApp/src/App.test.js b/Birdmap/ClientApp/src/App.test.js
new file mode 100644
index 0000000..c37d228
--- /dev/null
+++ b/Birdmap/ClientApp/src/App.test.js
@@ -0,0 +1,31 @@
+"use strict";
+var __assign = (this && this.__assign) || function () {
+ __assign = Object.assign || function(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
+ t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var React = require("react");
+var ReactDOM = require("react-dom");
+var react_redux_1 = require("react-redux");
+var react_router_dom_1 = require("react-router-dom");
+var App_1 = require("./App");
+it('renders without crashing', function () {
+ var storeFake = function (state) { return ({
+ default: function () { },
+ subscribe: function () { },
+ dispatch: function () { },
+ getState: function () { return (__assign({}, state)); }
+ }); };
+ var store = storeFake({});
+ ReactDOM.render(React.createElement(react_redux_1.Provider, { store: store },
+ React.createElement(react_router_dom_1.MemoryRouter, null,
+ React.createElement(App_1.default, null))), document.createElement('div'));
+});
+//# sourceMappingURL=App.test.js.map
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/App.test.js.map b/Birdmap/ClientApp/src/App.test.js.map
new file mode 100644
index 0000000..c25913f
--- /dev/null
+++ b/Birdmap/ClientApp/src/App.test.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"App.test.js","sourceRoot":"","sources":["App.test.tsx"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,6BAA+B;AAC/B,oCAAsC;AACtC,2CAAuC;AACvC,qDAAgD;AAChD,6BAAwB;AAExB,EAAE,CAAC,0BAA0B,EAAE;IAC3B,IAAM,SAAS,GAAG,UAAC,KAAU,IAAK,OAAA,CAAC;QAC/B,OAAO,EAAE,cAAO,CAAC;QACjB,SAAS,EAAE,cAAO,CAAC;QACnB,QAAQ,EAAE,cAAO,CAAC;QAClB,QAAQ,EAAE,cAAM,OAAA,cAAM,KAAK,EAAG,EAAd,CAAc;KACjC,CAAC,EALgC,CAKhC,CAAC;IACH,IAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAQ,CAAC;IAEnC,QAAQ,CAAC,MAAM,CACX,oBAAC,sBAAQ,IAAC,KAAK,EAAE,KAAK;QAClB,oBAAC,+BAAY;YACT,oBAAC,aAAG,OAAE,CACK,CACR,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC"}
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/App.tsx b/Birdmap/ClientApp/src/App.tsx
index 083c0f1..2d9441a 100644
--- a/Birdmap/ClientApp/src/App.tsx
+++ b/Birdmap/ClientApp/src/App.tsx
@@ -1,16 +1,93 @@
-import * as React from 'react';
-import { Route } from 'react-router';
-import Layout from './components/Layout';
+import { Box, Container } from '@material-ui/core';
+import AppBar from '@material-ui/core/AppBar';
+import blue from '@material-ui/core/colors/blue';
+import { createMuiTheme } from '@material-ui/core/styles';
+import Toolbar from '@material-ui/core/Toolbar';
+import Typography from '@material-ui/core/Typography';
+import { ThemeProvider } from '@material-ui/styles';
+import React, { useState } from 'react';
+import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
+import Auth from './components/auth/Auth';
+import AuthService from './components/auth/AuthService';
import Home from './components/Home';
-import Counter from './components/Counter';
-import FetchData from './components/FetchData';
+import './custom.css';
-import './custom.css'
-export default () => (
-
-
-
-
-
-);
+const theme = createMuiTheme({
+ palette: {
+ primary: {
+ main: blue[800]
+ },
+ },
+});
+
+function App() {
+ const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
+
+ const onAuthenticated = () => {
+ setAuthenticated(AuthService.isAuthenticated());
+ };
+
+ const LoginComponent = () => {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+export default App;
+
+const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
+ return (
+ (
+
+ )} />
+ );
+}
+
+const PrivateRoute = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
+ return (
+ (
+ Authenticated
+ ?
+ :
+ )} />
+ );
+};
+
+const NoLayout = ({ component: Component, ...rest }: { [x: string]: any, component: any }) => {
+ return (
+
+ );
+};
+
+const DefaultLayout = ({ component: Component, ...rest }: { [x: string]: any, component: any }) => {
+ return (
+
+
+
+
+
+ Dashboard
+ Login
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/common/ErrorDispatcher.js b/Birdmap/ClientApp/src/common/ErrorDispatcher.js
new file mode 100644
index 0000000..7ed460d
--- /dev/null
+++ b/Birdmap/ClientApp/src/common/ErrorDispatcher.js
@@ -0,0 +1,14 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var ErrorDispatcher = {
+ errorHandlers: [],
+ registerErrorHandler: function (errorHandlerFn) {
+ this.errorHandlers.push(errorHandlerFn);
+ },
+ raiseError: function (errorMessage) {
+ for (var i = 0; i < this.errorHandlers.length; i++)
+ this.errorHandlers[i](errorMessage);
+ }
+};
+exports.default = ErrorDispatcher;
+//# sourceMappingURL=ErrorDispatcher.js.map
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/common/ErrorDispatcher.js.map b/Birdmap/ClientApp/src/common/ErrorDispatcher.js.map
new file mode 100644
index 0000000..195e5dd
--- /dev/null
+++ b/Birdmap/ClientApp/src/common/ErrorDispatcher.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"ErrorDispatcher.js","sourceRoot":"","sources":["ErrorDispatcher.ts"],"names":[],"mappings":";;AAAA,IAAM,eAAe,GAAG;IACtB,aAAa,EAAE,EAAE;IAEjB,oBAAoB,YAAC,cAAc;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU,YAAC,YAAY;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE;YAChD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;CACF,CAAC;AAEF,kBAAe,eAAe,CAAC"}
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/common/ErrorDispatcher.ts b/Birdmap/ClientApp/src/common/ErrorDispatcher.ts
new file mode 100644
index 0000000..9c8e39d
--- /dev/null
+++ b/Birdmap/ClientApp/src/common/ErrorDispatcher.ts
@@ -0,0 +1,14 @@
+const ErrorDispatcher = {
+ errorHandlers: [],
+
+ registerErrorHandler(errorHandlerFn) {
+ this.errorHandlers.push(errorHandlerFn);
+ },
+
+ raiseError(errorMessage) {
+ for (let i = 0; i < this.errorHandlers.length; i++)
+ this.errorHandlers[i](errorMessage);
+ }
+};
+
+export default ErrorDispatcher;
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/common/ServiceBase.js b/Birdmap/ClientApp/src/common/ServiceBase.js
new file mode 100644
index 0000000..faa2c25
--- /dev/null
+++ b/Birdmap/ClientApp/src/common/ServiceBase.js
@@ -0,0 +1,50 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var ErrorDispatcher_1 = require("./ErrorDispatcher");
+function get(url) {
+ var options = {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': sessionStorage.getItem('user')
+ }
+ };
+ return makeRequest(url, options);
+}
+function post(url, request) {
+ var options = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': sessionStorage.getItem('user')
+ },
+ body: "",
+ };
+ if (request)
+ options.body = JSON.stringify(request);
+ return makeRequest(url, options);
+}
+function makeRequest(url, options) {
+ return fetch(url, options)
+ .then(ensureResponseSuccess)
+ .catch(errorHandler);
+}
+function ensureResponseSuccess(response) {
+ if (!response.ok)
+ return response.json()
+ .then(function (data) { return errorHandler(data); });
+ return response.text()
+ .then(function (text) { return text.length ? JSON.parse(text) : {}; });
+}
+function errorHandler(response) {
+ console.log(response);
+ if (response && response.Error)
+ ErrorDispatcher_1.default.raiseError(response.Error);
+ return Promise.reject();
+}
+exports.default = {
+ get: get,
+ post: post,
+ makeRequest: makeRequest
+};
+//# sourceMappingURL=ServiceBase.js.map
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/common/ServiceBase.js.map b/Birdmap/ClientApp/src/common/ServiceBase.js.map
new file mode 100644
index 0000000..8ae2c0e
--- /dev/null
+++ b/Birdmap/ClientApp/src/common/ServiceBase.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"ServiceBase.js","sourceRoot":"","sources":["ServiceBase.ts"],"names":[],"mappings":";;AAAA,qDAAgD;AAEhD,SAAS,GAAG,CAAC,GAAG;IACZ,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;KACJ,CAAC;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,IAAI,CAAC,GAAG,EAAE,OAAO;IACtB,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;QACD,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAAG,EAAE,OAAO;IAC7B,OAAO,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC;SACrB,IAAI,CAAC,qBAAqB,CAAC;SAC3B,KAAK,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAQ;IACnC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACZ,OAAO,QAAQ,CAAC,IAAI,EAAE;aACjB,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,YAAY,CAAC,IAAI,CAAC,EAAlB,CAAkB,CAAC,CAAC;IAE1C,OAAO,QAAQ,CAAC,IAAI,EAAE;SACjB,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAnC,CAAmC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,QAAQ;IAC1B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK;QAC1B,yBAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,kBAAe;IACX,GAAG,KAAA;IACH,IAAI,MAAA;IACJ,WAAW,aAAA;CACd,CAAC"}
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/common/ServiceBase.ts b/Birdmap/ClientApp/src/common/ServiceBase.ts
new file mode 100644
index 0000000..df29612
--- /dev/null
+++ b/Birdmap/ClientApp/src/common/ServiceBase.ts
@@ -0,0 +1,59 @@
+import ErrorDispatcher from './ErrorDispatcher';
+
+function get(url) {
+ let options = {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': sessionStorage.getItem('user')
+ }
+ };
+
+ return makeRequest(url, options);
+}
+
+function post(url, request) {
+ let options = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': sessionStorage.getItem('user')
+ },
+ body: "",
+ };
+
+ if (request)
+ options.body = JSON.stringify(request);
+
+ return makeRequest(url, options);
+}
+
+function makeRequest(url, options) {
+ return fetch(url, options)
+ .then(ensureResponseSuccess)
+ .catch(errorHandler);
+}
+
+function ensureResponseSuccess(response) {
+ if (!response.ok)
+ return response.json()
+ .then(data => errorHandler(data));
+
+ return response.text()
+ .then(text => text.length ? JSON.parse(text) : {});
+}
+
+function errorHandler(response) {
+ console.log(response);
+
+ if (response && response.Error)
+ ErrorDispatcher.raiseError(response.Error);
+
+ return Promise.reject();
+}
+
+export default {
+ get,
+ post,
+ makeRequest
+};
diff --git a/Birdmap/ClientApp/src/components/auth/Auth.tsx b/Birdmap/ClientApp/src/components/auth/Auth.tsx
index 5f28270..2136a1b 100644
--- a/Birdmap/ClientApp/src/components/auth/Auth.tsx
+++ b/Birdmap/ClientApp/src/components/auth/Auth.tsx
@@ -1 +1,119 @@
-
\ No newline at end of file
+import React, { useState } from 'react';
+import { useHistory } from 'react-router-dom';
+import { Box, Grid, TextField, Button, Typography, Paper } from '@material-ui/core';
+import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
+import AuthService from './AuthService';
+
+export default function MenuItem(props: any) {
+ const history = useHistory();
+ const classes = useStyles();
+
+ const [username, setUsername] = useState(null);
+ const [password, setPassword] = useState(null);
+
+ const [showError, setShowError] = useState(false);
+ const [errorMessage, setErrorMessage] = useState('');
+
+ const onUsernameChanged = (event: any) => {
+ setUsername(event.target.value);
+
+ setShowError(false);
+ setErrorMessage('');
+ };
+
+ const onPasswordChanged = (event: any) => {
+ setPassword(event.target.value);
+
+ setShowError(false);
+ setErrorMessage('');
+ };
+
+ const onPasswordKeyPress = (event: any) => {
+ if (event.key === 'Enter') {
+ onLoginClicked();
+ }
+ };
+
+ const onLoginClicked = () => {
+ if (!username) {
+ setShowError(true);
+ setErrorMessage('Username required');
+
+ return;
+ }
+
+ if (!password) {
+ setShowError(true);
+ setErrorMessage('Password required');
+
+ return;
+ }
+
+ AuthService.login(username, password).then(() => {
+ props.onAuthenticated();
+ history.push('/');
+
+ }).catch(() => {
+ setShowError(true);
+ setErrorMessage('Invalid credentials');
+ });
+ };
+
+ const renderErrorLabel = () => {
+ return showError
+ ? {errorMessage}
+ : ;
+ };
+
+ return (
+
+
+
+
+
+ Sign in
+
+
+
+
+
+
+
+
+
+ {renderErrorLabel()}
+
+
+
+
+
+
+
+ );
+};
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ root: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ minWidth: 400,
+ minHeight: 600,
+ },
+ container: {
+ padding: 40,
+ flexDirection: "column",
+ justifyContent: "space-around",
+ alignItems: "center",
+ },
+ paper: {
+ },
+ button: {
+ width: '100%',
+ },
+ error: {
+ color: "red",
+ }
+ }),
+);
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/components/auth/AuthService.js b/Birdmap/ClientApp/src/components/auth/AuthService.js
new file mode 100644
index 0000000..386b927
--- /dev/null
+++ b/Birdmap/ClientApp/src/components/auth/AuthService.js
@@ -0,0 +1,28 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var ServiceBase_1 = require("../../common/ServiceBase");
+var login_url = '/auth/authenticate';
+exports.default = {
+ isAuthenticated: function () {
+ return sessionStorage.getItem('user') !== null;
+ },
+ login: function (username, password) {
+ var body = {
+ username: username,
+ password: password
+ };
+ var options = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(body),
+ };
+ return ServiceBase_1.default.makeRequest(login_url, options)
+ .then(function (response) {
+ sessionStorage.setItem('user', response.token_type + " " + response.access_token);
+ return Promise.resolve();
+ });
+ }
+};
+//# sourceMappingURL=AuthService.js.map
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/components/auth/AuthService.js.map b/Birdmap/ClientApp/src/components/auth/AuthService.js.map
new file mode 100644
index 0000000..f9e2c3f
--- /dev/null
+++ b/Birdmap/ClientApp/src/components/auth/AuthService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,oBAAoB,CAAC;AAEvC,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,KAAK,YAAC,QAAQ,EAAE,QAAQ;QACpB,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/components/auth/AuthService.ts b/Birdmap/ClientApp/src/components/auth/AuthService.ts
new file mode 100644
index 0000000..f8e5cbe
--- /dev/null
+++ b/Birdmap/ClientApp/src/components/auth/AuthService.ts
@@ -0,0 +1,29 @@
+import ServiceBase from '../../common/ServiceBase';
+
+const login_url = '/auth/authenticate';
+
+export default {
+ isAuthenticated() {
+ return sessionStorage.getItem('user') !== null;
+ },
+
+ login(username, password) {
+ let body = {
+ username: username,
+ password: password
+ };
+ let options = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(body),
+ };
+
+ return ServiceBase.makeRequest(login_url, options)
+ .then(response => {
+ sessionStorage.setItem('user', `${response.token_type} ${response.access_token}`);
+ return Promise.resolve();
+ });
+ }
+}
diff --git a/Birdmap/ClientApp/src/index.js b/Birdmap/ClientApp/src/index.js
new file mode 100644
index 0000000..8c67f2c
--- /dev/null
+++ b/Birdmap/ClientApp/src/index.js
@@ -0,0 +1,21 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+require("bootstrap/dist/css/bootstrap.css");
+var React = require("react");
+var ReactDOM = require("react-dom");
+var react_redux_1 = require("react-redux");
+var connected_react_router_1 = require("connected-react-router");
+var history_1 = require("history");
+var configureStore_1 = require("./store/configureStore");
+var App_1 = require("./App");
+var registerServiceWorker_1 = require("./registerServiceWorker");
+// Create browser history to use in the Redux store
+var baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
+var history = history_1.createBrowserHistory({ basename: baseUrl });
+// Get the application-wide store instance, prepopulating with state from the server where available.
+var store = configureStore_1.default(history);
+ReactDOM.render(React.createElement(react_redux_1.Provider, { store: store },
+ React.createElement(connected_react_router_1.ConnectedRouter, { history: history },
+ React.createElement(App_1.default, null))), document.getElementById('root'));
+registerServiceWorker_1.default();
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/Birdmap/ClientApp/src/index.js.map b/Birdmap/ClientApp/src/index.js.map
new file mode 100644
index 0000000..b7168cf
--- /dev/null
+++ b/Birdmap/ClientApp/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":";;AAAA,4CAA0C;AAE1C,6BAA+B;AAC/B,oCAAsC;AACtC,2CAAuC;AACvC,iEAAyD;AACzD,mCAA+C;AAC/C,yDAAoD;AACpD,6BAAwB;AACxB,iEAA4D;AAE5D,mDAAmD;AACnD,IAAM,OAAO,GAAG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAW,CAAC;AACxF,IAAM,OAAO,GAAG,8BAAoB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAE5D,qGAAqG;AACrG,IAAM,KAAK,GAAG,wBAAc,CAAC,OAAO,CAAC,CAAC;AAEtC,QAAQ,CAAC,MAAM,CACX,oBAAC,sBAAQ,IAAC,KAAK,EAAE,KAAK;IAClB,oBAAC,wCAAe,IAAC,OAAO,EAAE,OAAO;QAC7B,oBAAC,aAAG,OAAG,CACO,CACX,EACX,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;AAErC,+BAAqB,EAAE,CAAC"}
\ No newline at end of file
diff --git a/Birdmap/Controllers/AuthController.cs b/Birdmap/Controllers/AuthController.cs
index fa70bc6..3df0d3c 100644
--- a/Birdmap/Controllers/AuthController.cs
+++ b/Birdmap/Controllers/AuthController.cs
@@ -33,7 +33,7 @@ namespace Birdmap.Controllers
public async Task AuthenticateAsync([FromBody] AuthenticateRequest model)
{
var user = await _service.AuthenticateUserAsync(model.Username, model.Password);
- var expires = DateTime.UtcNow.AddHours(2);
+ var expiresInSeconds = TimeSpan.FromHours(2).TotalSeconds;
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["BasicAuth:Secret"]);
var tokenDescriptor = new SecurityTokenDescriptor
@@ -42,7 +42,7 @@ namespace Birdmap.Controllers
{
new Claim(ClaimTypes.Name, user.Name)
}),
- Expires = expires,
+ Expires = DateTime.UtcNow.AddHours(expiresInSeconds),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
@@ -51,9 +51,10 @@ namespace Birdmap.Controllers
return Ok(
new
{
- Name = user.Name,
- Token = tokenString,
- Expires = expires,
+ user_name = user.Name,
+ access_token = tokenString,
+ token_type = "Bearer",
+ expires_in = expiresInSeconds,
});
}
}