Compare commits
93 Commits
version/20
...
version/20
Author | SHA1 | Date | |
---|---|---|---|
e20bb7d636 | |||
e9abc25b92 | |||
dc930c0cdf | |||
464a1c0536 | |||
837d2f6fab | |||
8f00d73512 | |||
b75feab709 | |||
9c8433ec4d | |||
ef080900a4 | |||
10b45a8dea | |||
c43ac1f704 | |||
14d702450a | |||
0a1a2a035e | |||
ace777ebbe | |||
8a6879afa5 | |||
fdc7f14056 | |||
8be80aaf9d | |||
e476f2dda2 | |||
5d48cfab14 | |||
1f22f0e7bb | |||
ce082ead5e | |||
dd2cd09637 | |||
828fe07fca | |||
a074ea70e9 | |||
84ce2c1df2 | |||
8628595590 | |||
7b8e5c4272 | |||
caa5dc1d14 | |||
f328b21e89 | |||
52abd959eb | |||
a0cd17a257 | |||
32c5bf04b8 | |||
766c4873a0 | |||
240136154b | |||
78dd7b0341 | |||
0021a93952 | |||
67240fb9ad | |||
4add0bbe86 | |||
d2dd7d1366 | |||
476e57daa2 | |||
4eb8a0dcd1 | |||
60615c9f3e | |||
b5b8573d87 | |||
2e44c1cdfc | |||
31909a4d78 | |||
4a444e667a | |||
f67b57e369 | |||
6be19962d2 | |||
262a9fa2a0 | |||
e8ba159756 | |||
0b03d66a2f | |||
7c858c9626 | |||
71b6839d03 | |||
ada49c077a | |||
7880c7fb98 | |||
2b48ba4103 | |||
5e67f68f2b | |||
1992b89154 | |||
9ab2088ab7 | |||
a9d0d96418 | |||
c476503594 | |||
de74f3ec1f | |||
ce98255607 | |||
53b9e5b93f | |||
7aeb390eac | |||
5df9ad63cf | |||
e4400476a2 | |||
ef3c01ec34 | |||
b136d3bc69 | |||
c34fcc73dc | |||
11b09c4ebd | |||
e32070ddeb | |||
33a8cea007 | |||
d01fd7cdb7 | |||
1770e42cbf | |||
2fed739be7 | |||
aa820b2b4d | |||
582d2eb5eb | |||
c5e2635903 | |||
cfe0a7a694 | |||
c579540473 | |||
35f2b06611 | |||
9c4f025d71 | |||
d8b8e8a5a3 | |||
ec34c3eb75 | |||
0554c94c53 | |||
19a663a645 | |||
e72881b2a9 | |||
4452ff171e | |||
39bdc3a9a9 | |||
33bb6edf8c | |||
2eb18ff5e6 | |||
aeb1b5e8f2 |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2021.4.1
|
||||
current_version = 2021.4.3
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
|
||||
|
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@ -18,11 +18,11 @@ jobs:
|
||||
- name: Building Docker Image
|
||||
run: docker build
|
||||
--no-cache
|
||||
-t beryju/authentik:2021.4.1
|
||||
-t beryju/authentik:2021.4.3
|
||||
-t beryju/authentik:latest
|
||||
-f Dockerfile .
|
||||
- name: Push Docker Container to Registry (versioned)
|
||||
run: docker push beryju/authentik:2021.4.1
|
||||
run: docker push beryju/authentik:2021.4.3
|
||||
- name: Push Docker Container to Registry (latest)
|
||||
run: docker push beryju/authentik:latest
|
||||
build-proxy:
|
||||
@ -48,11 +48,11 @@ jobs:
|
||||
cd outpost/
|
||||
docker build \
|
||||
--no-cache \
|
||||
-t beryju/authentik-proxy:2021.4.1 \
|
||||
-t beryju/authentik-proxy:2021.4.3 \
|
||||
-t beryju/authentik-proxy:latest \
|
||||
-f proxy.Dockerfile .
|
||||
- name: Push Docker Container to Registry (versioned)
|
||||
run: docker push beryju/authentik-proxy:2021.4.1
|
||||
run: docker push beryju/authentik-proxy:2021.4.3
|
||||
- name: Push Docker Container to Registry (latest)
|
||||
run: docker push beryju/authentik-proxy:latest
|
||||
build-static:
|
||||
@ -72,11 +72,11 @@ jobs:
|
||||
cd web/
|
||||
docker build \
|
||||
--no-cache \
|
||||
-t beryju/authentik-static:2021.4.1 \
|
||||
-t beryju/authentik-static:2021.4.3 \
|
||||
-t beryju/authentik-static:latest \
|
||||
-f Dockerfile .
|
||||
- name: Push Docker Container to Registry (versioned)
|
||||
run: docker push beryju/authentik-static:2021.4.1
|
||||
run: docker push beryju/authentik-static:2021.4.3
|
||||
- name: Push Docker Container to Registry (latest)
|
||||
run: docker push beryju/authentik-static:latest
|
||||
test-release:
|
||||
@ -110,5 +110,5 @@ jobs:
|
||||
SENTRY_PROJECT: authentik
|
||||
SENTRY_URL: https://sentry.beryju.org
|
||||
with:
|
||||
tagName: 2021.4.1
|
||||
tagName: 2021.4.3
|
||||
environment: beryjuorg-prod
|
||||
|
122
Pipfile.lock
generated
122
Pipfile.lock
generated
@ -116,18 +116,18 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:73bcd04f6f919e7f8acc27c9d83dab5aee22225fe624c028b2e1c7feaf771098",
|
||||
"sha256:c45e7d3aef8965ae1b42c9855c31ded19fbb38cfad0a34cc37dc880ded3672c2"
|
||||
"sha256:1d26f6e7ae3c940cb07119077ac42485dcf99164350da0ab50d0f5ad345800cd",
|
||||
"sha256:3bf3305571f3c8b738a53e9e7dcff59137dffe94670046c084a17f9fa4599ff3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.17.51"
|
||||
"version": "==1.17.53"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:ae45ea7451513373666b7571064c173d649e61fd3e8f413f0e1f1f9db26b3513",
|
||||
"sha256:c853d6c2321e2f2328282c7d49d7b1a06201826ba0e7049c6975ab5f22927ea8"
|
||||
"sha256:d5e70d17b91c9b5867be7d6de0caa7dde9ed789bed62f03ea9b60718dc9350bf",
|
||||
"sha256:e303500c4e80f6a706602da53daa6f751cfa8f491665c99a24ee732ab6321573"
|
||||
],
|
||||
"version": "==1.20.51"
|
||||
"version": "==1.20.53"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
@ -437,10 +437,10 @@
|
||||
},
|
||||
"google-auth": {
|
||||
"hashes": [
|
||||
"sha256:186fe2564634d67fbbb64f3daf8bc8c9cecbb2a7f535ed1a8a71795e50db8d87",
|
||||
"sha256:70b39558712826e41f65e5f05a8d879361deaf84df8883e5dd0ec3d0da6ab66e"
|
||||
"sha256:010f011c4e27d3d5eb01106fba6aac39d164842dfcd8709955c4638f5b11ccf8",
|
||||
"sha256:f30a672a64d91cc2e3137765d088c5deec26416246f7a9e956eaf69a8d7ed49c"
|
||||
],
|
||||
"version": "==1.28.1"
|
||||
"version": "==1.29.0"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
@ -1374,59 +1374,59 @@
|
||||
},
|
||||
"zope.interface": {
|
||||
"hashes": [
|
||||
"sha256:02d3535aa18e34ce97c58d241120b7554f7d1cf4f8002fc9675cc7e7745d20e8",
|
||||
"sha256:0378a42ec284b65706d9ef867600a4a31701a0d6773434e6537cfc744e3343f4",
|
||||
"sha256:07d289358a8c565ea09e426590dd1179f93cf5ac3dd17d43fcc4fc63c1a9d275",
|
||||
"sha256:0e6cdbdd94ae94d1433ab51f46a76df0f2cd041747c31baec1c1ffa4e76bd0c1",
|
||||
"sha256:11354fb8b8bdc5cdd66358ed4f1f0ce739d78ff6d215d33b8f3ae282258c0f11",
|
||||
"sha256:12588a46ae0a99f172c4524cbbc3bb870f32e0f8405e9fa11a5ef3fa3a808ad7",
|
||||
"sha256:16caa44a06f6b0b2f7626ced4b193c1ae5d09c1b49c9b4962c93ae8aa2134f55",
|
||||
"sha256:18c478b89b6505756f007dcf76a67224a23dcf0f365427742ed0c0473099caa4",
|
||||
"sha256:221b41442cf4428fcda7fc958c9721c916709e2a3a9f584edd70f1493a09a762",
|
||||
"sha256:26109c50ccbcc10f651f76277cfc05fba8418a907daccc300c9247f24b3158a2",
|
||||
"sha256:28d8157f8c77662a1e0796a7d3cfa8910289131d4b4dd4e10b2686ab1309b67b",
|
||||
"sha256:2c51689b7b40c7d9c7e8a678350e73dc647945a13b4e416e7a02bbf0c37bdb01",
|
||||
"sha256:2ec58e1e1691dde4fbbd97f8610de0f8f1b1a38593653f7d3b8e931b9cd6d67f",
|
||||
"sha256:416feb6500f7b6fc00d32271f6b8495e67188cb5eb51fc8e289b81fdf465a9cb",
|
||||
"sha256:520352b18adea5478bbf387e9c77910a914985671fe36bc5ef19fdcb67a854bc",
|
||||
"sha256:527415b5ca201b4add44026f70278fbc0b942cf0801a26ca5527cb0389b6151e",
|
||||
"sha256:54243053316b5eec92affe43bbace7c8cd946bc0974a4aa39ff1371df0677b22",
|
||||
"sha256:61b8454190b9cc87279232b6de28dee0bad040df879064bb2f0e505cda907918",
|
||||
"sha256:672668729edcba0f2ee522ab177fcad91c81cfce991c24d8767765e2637d3515",
|
||||
"sha256:67aa26097e194947d29f2b5a123830e03da1519bcce10cac034a51fcdb99c34f",
|
||||
"sha256:6e7305e42b5f54e5ccf51820de46f0a7c951ba7cb9e3f519e908545b0f5628d0",
|
||||
"sha256:7234ac6782ca43617de803735949f79b894f0c5d353fbc001d745503c69e6d1d",
|
||||
"sha256:7426bea25bdf92f00fa52c7b30fcd2a2f71c21cf007178971b1f248b6c2d3145",
|
||||
"sha256:74b331c5d5efdddf5bbd9e1f7d8cb91a0d6b9c4ba45ca3e9003047a84dca1a3b",
|
||||
"sha256:79b6db1a18253db86e9bf1e99fa829d60fd3fc7ac04f4451c44e4bdcf6756a42",
|
||||
"sha256:7d79cd354ae0a033ac7b86a2889c9e8bb0bb48243a6ed27fc5064ce49b842ada",
|
||||
"sha256:823d1b4a6a028b8327e64865e2c81a8959ae9f4e7c9c8e0eec814f4f9b36b362",
|
||||
"sha256:8715717a5861932b7fe7f3cbd498c82ff4132763e2fea182cc95e53850394ec1",
|
||||
"sha256:89a6091f2d07936c8a96ce56f2000ecbef20fb420a94845e7d53913c558a6378",
|
||||
"sha256:8af4b3116e4a37059bc8c7fe36d4a73d7c1d8802a1d8b6e549f1380d13a40160",
|
||||
"sha256:8b4b0034e6c7f30133fa64a1cc276f8f1a155ef9529e7eb93a3c1728b40c0f5c",
|
||||
"sha256:92195df3913c1de80062635bf64cd7bd0d0934a7fa1689b6d287d1cbbd16922c",
|
||||
"sha256:96c2e68385f3848d58f19b2975a675532abdb65c8fa5f04d94b95b27b6b1ffa7",
|
||||
"sha256:9c7044dbbf8c58420a9ef4ed6901f5a8b7698d90cd984d7f57a18c78474686f6",
|
||||
"sha256:a1937efed7e3fe0ee74630e1960df887d8aa83c571e1cf4db9d15b9c181d457d",
|
||||
"sha256:a38c10423a475a1658e2cb8f52cf84ec20a4c0adff724dd43a6b45183f499bc1",
|
||||
"sha256:a413c424199bcbab71bf5fa7538246f27177fbd6dd74b2d9c5f34878658807f8",
|
||||
"sha256:b18a855f8504743e0a2d8b75d008c7720d44e4c76687e13f959e35d9a13eb397",
|
||||
"sha256:b4d59ab3608538e550a72cea13d3c209dd72b6e19e832688da7884081c01594e",
|
||||
"sha256:b51d3f1cd87f488455f43046d72003689024b0fa9b2d53635db7523033b19996",
|
||||
"sha256:c02105deda867d09cdd5088d08708f06d75759df6f83d8f7007b06f422908a30",
|
||||
"sha256:c7b6032dc4490b0dcaf078f09f5b382dc35493cb7f473840368bf0de3196c2b6",
|
||||
"sha256:c95b355dba2aaf5177dff943b25ded0529a7feb80021d5fdb114a99f0a1ef508",
|
||||
"sha256:c980ae87863d76b1ea9a073d6d95554b4135032d34bc541be50c07d4a085821b",
|
||||
"sha256:d12895cd083e35e9e032eb4b57645b91116f8979527381a8d864d1f6b8cb4a2e",
|
||||
"sha256:d3cd9bad547a8e5fbe712a1dc1413aff1b917e8d39a2cd1389a6f933b7a21460",
|
||||
"sha256:e8809b01f27f679e3023b9e2013051e0a3f17abff4228cb5197663afd8a0f2c7",
|
||||
"sha256:f3c37b0dc1898e305aad4f7a1d75f6da83036588c28a9ce0afc681ff5245a601",
|
||||
"sha256:f966765f54b536e791541458de84a737a6adba8467190f17a8fe7f85354ba908",
|
||||
"sha256:fa939c2e2468142c9773443d4038e7c915b0cc1b670d3c9192bdc503f7ea73e9",
|
||||
"sha256:fcc5c1f95102989d2e116ffc8467963554ce89f30a65a3ea86a4d06849c498d8"
|
||||
"sha256:08f9636e99a9d5410181ba0729e0408d3d8748026ea938f3b970a0249daa8192",
|
||||
"sha256:0b465ae0962d49c68aa9733ba92a001b2a0933c317780435f00be7ecb959c702",
|
||||
"sha256:0cba8477e300d64a11a9789ed40ee8932b59f9ee05f85276dbb4b59acee5dd09",
|
||||
"sha256:0cee5187b60ed26d56eb2960136288ce91bcf61e2a9405660d271d1f122a69a4",
|
||||
"sha256:0ea1d73b7c9dcbc5080bb8aaffb776f1c68e807767069b9ccdd06f27a161914a",
|
||||
"sha256:0f91b5b948686659a8e28b728ff5e74b1be6bf40cb04704453617e5f1e945ef3",
|
||||
"sha256:15e7d1f7a6ee16572e21e3576d2012b2778cbacf75eb4b7400be37455f5ca8bf",
|
||||
"sha256:17776ecd3a1fdd2b2cd5373e5ef8b307162f581c693575ec62e7c5399d80794c",
|
||||
"sha256:194d0bcb1374ac3e1e023961610dc8f2c78a0f5f634d0c737691e215569e640d",
|
||||
"sha256:1c0e316c9add0db48a5b703833881351444398b04111188069a26a61cfb4df78",
|
||||
"sha256:205e40ccde0f37496904572035deea747390a8b7dc65146d30b96e2dd1359a83",
|
||||
"sha256:273f158fabc5ea33cbc936da0ab3d4ba80ede5351babc4f577d768e057651531",
|
||||
"sha256:2876246527c91e101184f63ccd1d716ec9c46519cc5f3d5375a3351c46467c46",
|
||||
"sha256:2c98384b254b37ce50eddd55db8d381a5c53b4c10ee66e1e7fe749824f894021",
|
||||
"sha256:2e5a26f16503be6c826abca904e45f1a44ff275fdb7e9d1b75c10671c26f8b94",
|
||||
"sha256:334701327f37c47fa628fc8b8d28c7d7730ce7daaf4bda1efb741679c2b087fc",
|
||||
"sha256:3748fac0d0f6a304e674955ab1365d515993b3a0a865e16a11ec9d86fb307f63",
|
||||
"sha256:3c02411a3b62668200910090a0dff17c0b25aaa36145082a5a6adf08fa281e54",
|
||||
"sha256:3dd4952748521205697bc2802e4afac5ed4b02909bb799ba1fe239f77fd4e117",
|
||||
"sha256:3f24df7124c323fceb53ff6168da70dbfbae1442b4f3da439cd441681f54fe25",
|
||||
"sha256:469e2407e0fe9880ac690a3666f03eb4c3c444411a5a5fddfdabc5d184a79f05",
|
||||
"sha256:4de4bc9b6d35c5af65b454d3e9bc98c50eb3960d5a3762c9438df57427134b8e",
|
||||
"sha256:5208ebd5152e040640518a77827bdfcc73773a15a33d6644015b763b9c9febc1",
|
||||
"sha256:52de7fc6c21b419078008f697fd4103dbc763288b1406b4562554bd47514c004",
|
||||
"sha256:5bb3489b4558e49ad2c5118137cfeaf59434f9737fa9c5deefc72d22c23822e2",
|
||||
"sha256:5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e",
|
||||
"sha256:5dd9ca406499444f4c8299f803d4a14edf7890ecc595c8b1c7115c2342cadc5f",
|
||||
"sha256:5f931a1c21dfa7a9c573ec1f50a31135ccce84e32507c54e1ea404894c5eb96f",
|
||||
"sha256:63b82bb63de7c821428d513607e84c6d97d58afd1fe2eb645030bdc185440120",
|
||||
"sha256:66c0061c91b3b9cf542131148ef7ecbecb2690d48d1612ec386de9d36766058f",
|
||||
"sha256:6f0c02cbb9691b7c91d5009108f975f8ffeab5dff8f26d62e21c493060eff2a1",
|
||||
"sha256:71aace0c42d53abe6fc7f726c5d3b60d90f3c5c055a447950ad6ea9cec2e37d9",
|
||||
"sha256:7d97a4306898b05404a0dcdc32d9709b7d8832c0c542b861d9a826301719794e",
|
||||
"sha256:7df1e1c05304f26faa49fa752a8c690126cf98b40b91d54e6e9cc3b7d6ffe8b7",
|
||||
"sha256:8270252effc60b9642b423189a2fe90eb6b59e87cbee54549db3f5562ff8d1b8",
|
||||
"sha256:867a5ad16892bf20e6c4ea2aab1971f45645ff3102ad29bd84c86027fa99997b",
|
||||
"sha256:877473e675fdcc113c138813a5dd440da0769a2d81f4d86614e5d62b69497155",
|
||||
"sha256:8892f89999ffd992208754851e5a052f6b5db70a1e3f7d54b17c5211e37a98c7",
|
||||
"sha256:9a9845c4c6bb56e508651f005c4aeb0404e518c6f000d5a1123ab077ab769f5c",
|
||||
"sha256:a1e6e96217a0f72e2b8629e271e1b280c6fa3fe6e59fa8f6701bec14e3354325",
|
||||
"sha256:a8156e6a7f5e2a0ff0c5b21d6bcb45145efece1909efcbbbf48c56f8da68221d",
|
||||
"sha256:a9506a7e80bcf6eacfff7f804c0ad5350c8c95b9010e4356a4b36f5322f09abb",
|
||||
"sha256:af310ec8335016b5e52cae60cda4a4f2a60a788cbb949a4fbea13d441aa5a09e",
|
||||
"sha256:b0297b1e05fd128d26cc2460c810d42e205d16d76799526dfa8c8ccd50e74959",
|
||||
"sha256:bf68f4b2b6683e52bec69273562df15af352e5ed25d1b6641e7efddc5951d1a7",
|
||||
"sha256:d0c1bc2fa9a7285719e5678584f6b92572a5b639d0e471bb8d4b650a1a910920",
|
||||
"sha256:d4d9d6c1a455d4babd320203b918ccc7fcbefe308615c521062bc2ba1aa4d26e",
|
||||
"sha256:db1fa631737dab9fa0b37f3979d8d2631e348c3b4e8325d6873c2541d0ae5a48",
|
||||
"sha256:dd93ea5c0c7f3e25335ab7d22a507b1dc43976e1345508f845efc573d3d779d8",
|
||||
"sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4",
|
||||
"sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263"
|
||||
],
|
||||
"version": "==5.3.0"
|
||||
"version": "==5.4.0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://discord.gg/KPnmtNWy)
|
||||
[](https://discord.gg/jg33eMhnj6)
|
||||
[](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=1)
|
||||
[](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=1)
|
||||
[](https://codecov.io/gh/BeryJu/authentik)
|
||||
|
@ -1,3 +1,3 @@
|
||||
"""authentik"""
|
||||
__version__ = "2021.4.1"
|
||||
__version__ = "2021.4.3"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
@ -4,6 +4,7 @@ from binascii import Error
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from rest_framework.authentication import BaseAuthentication, get_authorization_header
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
from rest_framework.request import Request
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
@ -14,7 +15,7 @@ LOGGER = get_logger()
|
||||
|
||||
# pylint: disable=too-many-return-statements
|
||||
def token_from_header(raw_header: bytes) -> Optional[Token]:
|
||||
"""raw_header in the Format of `Basic dGVzdDp0ZXN0`"""
|
||||
"""raw_header in the Format of `Bearer dGVzdDp0ZXN0`"""
|
||||
auth_credentials = raw_header.decode()
|
||||
if auth_credentials == "":
|
||||
return None
|
||||
@ -25,28 +26,27 @@ def token_from_header(raw_header: bytes) -> Optional[Token]:
|
||||
auth_type, body = plain.split()
|
||||
auth_credentials = f"{auth_type} {b64encode(body.encode()).decode()}"
|
||||
except (UnicodeDecodeError, Error):
|
||||
return None
|
||||
raise AuthenticationFailed("Malformed header")
|
||||
auth_type, auth_credentials = auth_credentials.split()
|
||||
if auth_type.lower() not in ["basic", "bearer"]:
|
||||
LOGGER.debug("Unsupported authentication type, denying", type=auth_type.lower())
|
||||
return None
|
||||
raise AuthenticationFailed("Unsupported authentication type")
|
||||
password = auth_credentials
|
||||
if auth_type.lower() == "basic":
|
||||
try:
|
||||
auth_credentials = b64decode(auth_credentials.encode()).decode()
|
||||
except (UnicodeDecodeError, Error):
|
||||
return None
|
||||
raise AuthenticationFailed("Malformed header")
|
||||
# Accept credentials with username and without
|
||||
if ":" in auth_credentials:
|
||||
_, password = auth_credentials.split(":")
|
||||
else:
|
||||
password = auth_credentials
|
||||
if password == "": # nosec
|
||||
return None
|
||||
raise AuthenticationFailed("Malformed header")
|
||||
tokens = Token.filter_not_expired(key=password, intent=TokenIntents.INTENT_API)
|
||||
if not tokens.exists():
|
||||
LOGGER.debug("Token not found")
|
||||
return None
|
||||
raise AuthenticationFailed("Token invalid/expired")
|
||||
return tokens.first()
|
||||
|
||||
|
||||
@ -58,10 +58,8 @@ class AuthentikTokenAuthentication(BaseAuthentication):
|
||||
auth = get_authorization_header(request)
|
||||
|
||||
token = token_from_header(auth)
|
||||
# None is only returned when the header isn't set.
|
||||
if not token:
|
||||
return None
|
||||
|
||||
return (token.user, None)
|
||||
|
||||
def authenticate_header(self, request: Request) -> str:
|
||||
return "Bearer"
|
||||
|
@ -11,6 +11,29 @@ authentik API Browser
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<script>
|
||||
function getCookie(name) {
|
||||
let cookieValue = "";
|
||||
if (document.cookie && document.cookie !== "") {
|
||||
const cookies = document.cookie.split(";");
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) === name + "=") {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
window.addEventListener('DOMContentLoaded', (event) => {
|
||||
const rapidocEl = document.querySelector('rapi-doc');
|
||||
rapidocEl.addEventListener('before-try', (e) => {
|
||||
e.detail.request.headers.append('X-CSRFToken', getCookie("authentik_csrf"));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<rapi-doc
|
||||
spec-url="{{ path }}"
|
||||
heading-text="authentik"
|
||||
|
@ -3,6 +3,7 @@ from base64 import b64encode
|
||||
|
||||
from django.test import TestCase
|
||||
from guardian.shortcuts import get_anonymous_user
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
|
||||
from authentik.api.auth import token_from_header
|
||||
from authentik.core.models import Token, TokenIntents
|
||||
@ -28,17 +29,21 @@ class TestAPIAuth(TestCase):
|
||||
|
||||
def test_invalid_type(self):
|
||||
"""Test invalid type"""
|
||||
self.assertIsNone(token_from_header("foo bar".encode()))
|
||||
with self.assertRaises(AuthenticationFailed):
|
||||
token_from_header("foo bar".encode())
|
||||
|
||||
def test_invalid_decode(self):
|
||||
"""Test invalid bas64"""
|
||||
self.assertIsNone(token_from_header("Basic bar".encode()))
|
||||
with self.assertRaises(AuthenticationFailed):
|
||||
token_from_header("Basic bar".encode())
|
||||
|
||||
def test_invalid_empty_password(self):
|
||||
"""Test invalid with empty password"""
|
||||
self.assertIsNone(token_from_header("Basic :".encode()))
|
||||
with self.assertRaises(AuthenticationFailed):
|
||||
token_from_header("Basic :".encode())
|
||||
|
||||
def test_invalid_no_token(self):
|
||||
"""Test invalid with no token"""
|
||||
auth = b64encode(":abc".encode()).decode()
|
||||
self.assertIsNone(token_from_header(f"Basic :{auth}".encode()))
|
||||
with self.assertRaises(AuthenticationFailed):
|
||||
auth = b64encode(":abc".encode()).decode()
|
||||
self.assertIsNone(token_from_header(f"Basic :{auth}".encode()))
|
||||
|
@ -113,6 +113,7 @@ router.register("core/user_consent", UserConsentViewSet)
|
||||
router.register("core/tokens", TokenViewSet)
|
||||
|
||||
router.register("outposts/outposts", OutpostViewSet)
|
||||
router.register("outposts/instances", OutpostViewSet)
|
||||
router.register("outposts/service_connections/all", ServiceConnectionViewSet)
|
||||
router.register("outposts/service_connections/docker", DockerServiceConnectionViewSet)
|
||||
router.register(
|
||||
|
@ -91,6 +91,15 @@ class ApplicationViewSet(ModelViewSet):
|
||||
applications.append(application)
|
||||
return applications
|
||||
|
||||
@swagger_auto_schema(
|
||||
manual_parameters=[
|
||||
openapi.Parameter(
|
||||
name="superuser_full_list",
|
||||
in_=openapi.IN_QUERY,
|
||||
type=openapi.TYPE_BOOLEAN,
|
||||
)
|
||||
]
|
||||
)
|
||||
def list(self, request: Request) -> Response:
|
||||
"""Custom list method that checks Policy based access instead of guardian"""
|
||||
queryset = self._filter_queryset_for_list(self.get_queryset())
|
||||
@ -98,6 +107,13 @@ class ApplicationViewSet(ModelViewSet):
|
||||
|
||||
should_cache = request.GET.get("search", "") == ""
|
||||
|
||||
superuser_full_list = (
|
||||
str(request.GET.get("superuser_full_list", "false")).lower() == "true"
|
||||
)
|
||||
if superuser_full_list and request.user.is_superuser:
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
|
||||
allowed_applications = []
|
||||
if not should_cache:
|
||||
allowed_applications = self._get_allowed_applications(queryset)
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""PropertyMapping API Views"""
|
||||
from json import dumps
|
||||
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
from rest_framework import mixins
|
||||
@ -91,7 +92,9 @@ class PropertyMappingViewSet(
|
||||
{
|
||||
"name": subclass._meta.verbose_name,
|
||||
"description": subclass.__doc__,
|
||||
"component": subclass.component,
|
||||
# pyright: reportGeneralTypeIssues=false
|
||||
"component": subclass().component,
|
||||
"model_name": subclass._meta.model_name,
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
@ -100,6 +103,13 @@ class PropertyMappingViewSet(
|
||||
@swagger_auto_schema(
|
||||
request_body=PolicyTestSerializer(),
|
||||
responses={200: PropertyMappingTestResultSerializer, 400: "Invalid parameters"},
|
||||
manual_parameters=[
|
||||
openapi.Parameter(
|
||||
name="format_result",
|
||||
in_=openapi.IN_QUERY,
|
||||
type=openapi.TYPE_BOOLEAN,
|
||||
)
|
||||
],
|
||||
)
|
||||
@action(detail=True, pagination_class=None, filter_backends=[], methods=["POST"])
|
||||
# pylint: disable=unused-argument, invalid-name
|
||||
@ -110,6 +120,8 @@ class PropertyMappingViewSet(
|
||||
if not test_params.is_valid():
|
||||
return Response(test_params.errors, status=400)
|
||||
|
||||
format_result = str(request.GET.get("format_result", "false")).lower() == "true"
|
||||
|
||||
# User permission check, only allow mapping testing for users that are readable
|
||||
users = get_objects_for_user(request.user, "authentik_core.view_user").filter(
|
||||
pk=test_params.validated_data["user"].pk
|
||||
@ -124,7 +136,9 @@ class PropertyMappingViewSet(
|
||||
self.request,
|
||||
**test_params.validated_data.get("context", {}),
|
||||
)
|
||||
response_data["result"] = dumps(result)
|
||||
response_data["result"] = dumps(
|
||||
result, indent=(4 if format_result else None)
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
response_data["result"] = str(exc)
|
||||
response_data["successful"] = False
|
||||
|
@ -78,6 +78,7 @@ class ProviderViewSet(
|
||||
"name": subclass._meta.verbose_name,
|
||||
"description": subclass.__doc__,
|
||||
"component": subclass().component,
|
||||
"model_name": subclass._meta.model_name,
|
||||
}
|
||||
)
|
||||
data.append(
|
||||
@ -85,6 +86,7 @@ class ProviderViewSet(
|
||||
"name": _("SAML Provider from Metadata"),
|
||||
"description": _("Create a SAML Provider by importing its Metadata."),
|
||||
"component": "ak-provider-saml-import-form",
|
||||
"model_name": "",
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
|
@ -81,6 +81,7 @@ class SourceViewSet(
|
||||
"name": subclass._meta.verbose_name,
|
||||
"description": subclass.__doc__,
|
||||
"component": component,
|
||||
"model_name": subclass._meta.model_name,
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
|
@ -11,7 +11,7 @@ from rest_framework.viewsets import ModelViewSet
|
||||
from authentik.api.decorators import permission_required
|
||||
from authentik.core.api.users import UserSerializer
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.core.models import Token
|
||||
from authentik.core.models import Token, TokenIntents
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.managed.api import ManagedSerializer
|
||||
|
||||
@ -64,7 +64,7 @@ class TokenViewSet(ModelViewSet):
|
||||
ordering = ["expires"]
|
||||
|
||||
def perform_create(self, serializer: TokenSerializer):
|
||||
serializer.save(user=self.request.user)
|
||||
serializer.save(user=self.request.user, intent=TokenIntents.INTENT_API)
|
||||
|
||||
@permission_required("authentik_core.view_token_key")
|
||||
@swagger_auto_schema(
|
||||
|
@ -1,4 +1,5 @@
|
||||
"""User API Views"""
|
||||
from django.http.response import Http404
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.http import urlencode
|
||||
from drf_yasg.utils import swagger_auto_schema, swagger_serializer_method
|
||||
@ -19,6 +20,7 @@ from authentik.core.middleware import (
|
||||
)
|
||||
from authentik.core.models import Token, TokenIntents, User
|
||||
from authentik.events.models import EventAction
|
||||
from authentik.flows.models import Flow, FlowDesignation
|
||||
|
||||
|
||||
class UserSerializer(ModelSerializer):
|
||||
@ -121,12 +123,16 @@ class UserViewSet(ModelViewSet):
|
||||
|
||||
@permission_required("authentik_core.reset_user_password")
|
||||
@swagger_auto_schema(
|
||||
responses={"200": LinkSerializer(many=False)},
|
||||
responses={"200": LinkSerializer(many=False), "404": "No recovery flow found."},
|
||||
)
|
||||
@action(detail=True, pagination_class=None, filter_backends=[])
|
||||
# pylint: disable=invalid-name, unused-argument
|
||||
def recovery(self, request: Request, pk: int) -> Response:
|
||||
"""Create a temporary link that a user can use to recover their accounts"""
|
||||
# Check that there is a recovery flow, if not return an error
|
||||
flow = Flow.with_policy(request, designation=FlowDesignation.RECOVERY)
|
||||
if not flow:
|
||||
raise Http404
|
||||
user: User = self.get_object()
|
||||
token, __ = Token.objects.get_or_create(
|
||||
identifier=f"{user.uid}-password-reset",
|
||||
|
@ -48,6 +48,7 @@ class TypeCreateSerializer(PassiveSerializer):
|
||||
name = CharField(required=True)
|
||||
description = CharField(required=True)
|
||||
component = CharField(required=True)
|
||||
model_name = CharField(required=True)
|
||||
|
||||
|
||||
class CacheSerializer(PassiveSerializer):
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Channels base classes"""
|
||||
from channels.exceptions import DenyConnection
|
||||
from channels.generic.websocket import JsonWebsocketConsumer
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.api.auth import token_from_header
|
||||
@ -22,9 +23,13 @@ class AuthJsonConsumer(JsonWebsocketConsumer):
|
||||
|
||||
raw_header = headers[b"authorization"]
|
||||
|
||||
token = token_from_header(raw_header)
|
||||
if not token:
|
||||
LOGGER.warning("Failed to authenticate")
|
||||
try:
|
||||
token = token_from_header(raw_header)
|
||||
# token is only None when no header was given, in which case we deny too
|
||||
if not token:
|
||||
raise DenyConnection()
|
||||
except AuthenticationFailed as exc:
|
||||
LOGGER.warning("Failed to authenticate", exc=exc)
|
||||
raise DenyConnection()
|
||||
|
||||
self.user = token.user
|
||||
|
@ -2,7 +2,7 @@
|
||||
from django.urls.base import reverse
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.core.models import Token, User
|
||||
from authentik.core.models import Token, TokenIntents, User
|
||||
|
||||
|
||||
class TestTokenAPI(APITestCase):
|
||||
@ -19,4 +19,6 @@ class TestTokenAPI(APITestCase):
|
||||
reverse("authentik_api:token-list"), {"identifier": "test-token"}
|
||||
)
|
||||
self.assertEqual(response.status_code, 201)
|
||||
self.assertEqual(Token.objects.get(identifier="test-token").user, self.user)
|
||||
token = Token.objects.get(identifier="test-token")
|
||||
self.assertEqual(token.user, self.user)
|
||||
self.assertEqual(token.intent, TokenIntents.INTENT_API)
|
||||
|
@ -153,10 +153,6 @@ class EventViewSet(ReadOnlyModelViewSet):
|
||||
data = []
|
||||
for value, name in EventAction.choices:
|
||||
data.append(
|
||||
{
|
||||
"name": name,
|
||||
"description": "",
|
||||
"component": value,
|
||||
}
|
||||
{"name": name, "description": "", "component": value, "model_name": ""}
|
||||
)
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
|
@ -4,6 +4,7 @@ from typing import Iterable
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework import mixins
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.fields import BooleanField
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
|
||||
@ -19,6 +20,12 @@ from authentik.lib.utils.reflection import all_subclasses
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
class StageUserSettingSerializer(UserSettingSerializer):
|
||||
"""User settings but can include a configure flow"""
|
||||
|
||||
configure_flow = BooleanField(required=False)
|
||||
|
||||
|
||||
class StageSerializer(ModelSerializer, MetaNameSerializer):
|
||||
"""Stage Serializer"""
|
||||
|
||||
@ -73,12 +80,13 @@ class StageViewSet(
|
||||
"name": subclass._meta.verbose_name,
|
||||
"description": subclass.__doc__,
|
||||
"component": subclass().component,
|
||||
"model_name": subclass._meta.model_name,
|
||||
}
|
||||
)
|
||||
data = sorted(data, key=lambda x: x["name"])
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
|
||||
@swagger_auto_schema(responses={200: UserSettingSerializer(many=True)})
|
||||
@swagger_auto_schema(responses={200: StageUserSettingSerializer(many=True)})
|
||||
@action(detail=False, pagination_class=None, filter_backends=[])
|
||||
def user_settings(self, request: Request) -> Response:
|
||||
"""Get all stages the user can configure"""
|
||||
@ -89,6 +97,10 @@ class StageViewSet(
|
||||
if not user_settings:
|
||||
continue
|
||||
user_settings.initial_data["object_uid"] = str(stage.pk)
|
||||
if hasattr(stage, "configure_flow"):
|
||||
user_settings.initial_data["configure_flow"] = bool(
|
||||
stage.configure_flow
|
||||
)
|
||||
if not user_settings.is_valid():
|
||||
LOGGER.warning(user_settings.errors)
|
||||
matching_stages.append(user_settings.initial_data)
|
||||
|
@ -127,6 +127,7 @@ class FlowExecutorView(APIView):
|
||||
@swagger_auto_schema(
|
||||
responses={
|
||||
200: Challenge(),
|
||||
404: "No Token found", # This error can be raised by the email stage
|
||||
},
|
||||
request_body=no_body,
|
||||
manual_parameters=[
|
||||
|
@ -82,6 +82,7 @@ class ServiceConnectionViewSet(
|
||||
"name": subclass._meta.verbose_name,
|
||||
"description": subclass.__doc__,
|
||||
"component": subclass().component,
|
||||
"model_name": subclass._meta.model_name,
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
|
@ -356,7 +356,7 @@ class Outpost(models.Model):
|
||||
intent=TokenIntents.INTENT_API,
|
||||
description=f"Autogenerated by authentik for Outpost {self.name}",
|
||||
expiring=False,
|
||||
managed="goauthentik.io/outpost",
|
||||
managed=f"goauthentik.io/outpost/{self.token_identifier}",
|
||||
)
|
||||
|
||||
def get_required_objects(self) -> Iterable[models.Model]:
|
||||
|
@ -67,6 +67,8 @@ def outpost_controller(self: MonitoredTask, outpost_pk: str):
|
||||
outpost: Outpost = Outpost.objects.get(pk=outpost_pk)
|
||||
self.set_uid(slugify(outpost.name))
|
||||
try:
|
||||
if not outpost.service_connection:
|
||||
return
|
||||
if outpost.type == OutpostType.PROXY:
|
||||
service_connection = outpost.service_connection
|
||||
if isinstance(service_connection, DockerServiceConnection):
|
||||
|
@ -108,6 +108,7 @@ class PolicyViewSet(
|
||||
"name": subclass._meta.verbose_name,
|
||||
"description": subclass.__doc__,
|
||||
"component": subclass().component,
|
||||
"model_name": subclass._meta.model_name,
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(data, many=True).data)
|
||||
|
@ -1,13 +1,23 @@
|
||||
"""Test authorize view"""
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from authentik.core.models import Application, User
|
||||
from authentik.flows.challenge import ChallengeTypes
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.providers.oauth2.errors import (
|
||||
AuthorizeError,
|
||||
ClientIdError,
|
||||
RedirectUriError,
|
||||
)
|
||||
from authentik.providers.oauth2.models import OAuth2Provider
|
||||
from authentik.providers.oauth2.generators import generate_client_id
|
||||
from authentik.providers.oauth2.models import (
|
||||
AuthorizationCode,
|
||||
GrantTypes,
|
||||
OAuth2Provider,
|
||||
RefreshToken,
|
||||
)
|
||||
from authentik.providers.oauth2.views.authorize import OAuthAuthorizationParams
|
||||
|
||||
|
||||
@ -32,15 +42,194 @@ class TestViewsAuthorize(TestCase):
|
||||
)
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
|
||||
def test_missing_redirect_uri(self):
|
||||
"""test missing redirect URI"""
|
||||
def test_request(self):
|
||||
"""test request param"""
|
||||
OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id="test",
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
with self.assertRaises(AuthorizeError):
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://local.invalid",
|
||||
"request": "foo",
|
||||
},
|
||||
)
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
|
||||
def test_redirect_uri(self):
|
||||
"""test missing/invalid redirect URI"""
|
||||
OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id="test",
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
with self.assertRaises(RedirectUriError):
|
||||
request = self.factory.get(
|
||||
"/", data={"response_type": "code", "client_id": "test"}
|
||||
)
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
with self.assertRaises(RedirectUriError):
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://localhost",
|
||||
},
|
||||
)
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
|
||||
def test_response_type(self):
|
||||
"""test response_type"""
|
||||
OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id="test",
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://local.invalid",
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
OAuthAuthorizationParams.from_request(request).grant_type,
|
||||
GrantTypes.AUTHORIZATION_CODE,
|
||||
)
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "id_token",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://local.invalid",
|
||||
"scope": "openid",
|
||||
"state": "foo",
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
OAuthAuthorizationParams.from_request(request).grant_type,
|
||||
GrantTypes.IMPLICIT,
|
||||
)
|
||||
# Implicit without openid scope
|
||||
with self.assertRaises(AuthorizeError):
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "id_token",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://local.invalid",
|
||||
"state": "foo",
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
OAuthAuthorizationParams.from_request(request).grant_type,
|
||||
GrantTypes.IMPLICIT,
|
||||
)
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "code token",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://local.invalid",
|
||||
"scope": "openid",
|
||||
"state": "foo",
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
OAuthAuthorizationParams.from_request(request).grant_type, GrantTypes.HYBRID
|
||||
)
|
||||
with self.assertRaises(AuthorizeError):
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "invalid",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "http://local.invalid",
|
||||
},
|
||||
)
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
|
||||
def test_full_code(self):
|
||||
"""Test full authorization"""
|
||||
flow = Flow.objects.create(slug="empty")
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id="test",
|
||||
authorization_flow=flow,
|
||||
redirect_uris="http://localhost",
|
||||
)
|
||||
Application.objects.create(name="app", slug="app", provider=provider)
|
||||
state = generate_client_id()
|
||||
user = User.objects.get(username="akadmin")
|
||||
self.client.force_login(user)
|
||||
# Step 1, initiate params and get redirect to flow
|
||||
self.client.get(
|
||||
reverse("authentik_providers_oauth2:authorize"),
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"state": state,
|
||||
"redirect_uri": "http://localhost",
|
||||
},
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first()
|
||||
self.assertJSONEqual(
|
||||
force_str(response.content),
|
||||
{
|
||||
"type": ChallengeTypes.REDIRECT.value,
|
||||
"to": f"http://localhost?code={code.code}&state={state}",
|
||||
},
|
||||
)
|
||||
|
||||
def test_full_implicit(self):
|
||||
"""Test full authorization"""
|
||||
flow = Flow.objects.create(slug="empty")
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id="test",
|
||||
authorization_flow=flow,
|
||||
redirect_uris="http://localhost",
|
||||
)
|
||||
Application.objects.create(name="app", slug="app", provider=provider)
|
||||
state = generate_client_id()
|
||||
user = User.objects.get(username="akadmin")
|
||||
self.client.force_login(user)
|
||||
# Step 1, initiate params and get redirect to flow
|
||||
self.client.get(
|
||||
reverse("authentik_providers_oauth2:authorize"),
|
||||
data={
|
||||
"response_type": "id_token",
|
||||
"client_id": "test",
|
||||
"state": state,
|
||||
"scope": "openid",
|
||||
"redirect_uri": "http://localhost",
|
||||
},
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
token: RefreshToken = RefreshToken.objects.filter(user=user).first()
|
||||
self.assertJSONEqual(
|
||||
force_str(response.content),
|
||||
{
|
||||
"type": ChallengeTypes.REDIRECT.value,
|
||||
"to": (
|
||||
f"http://localhost#access_token={token.access_token}"
|
||||
f"&id_token={provider.encode(token.id_token.to_dict())}&token_type=bearer"
|
||||
f"&expires_in=600&state={state}"
|
||||
),
|
||||
},
|
||||
)
|
||||
|
171
authentik/providers/oauth2/tests/test_views_token.py
Normal file
171
authentik/providers/oauth2/tests/test_views_token.py
Normal file
@ -0,0 +1,171 @@
|
||||
"""Test token view"""
|
||||
from base64 import b64encode
|
||||
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.providers.oauth2.constants import (
|
||||
GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
GRANT_TYPE_REFRESH_TOKEN,
|
||||
)
|
||||
from authentik.providers.oauth2.generators import (
|
||||
generate_client_id,
|
||||
generate_client_secret,
|
||||
)
|
||||
from authentik.providers.oauth2.models import (
|
||||
AuthorizationCode,
|
||||
OAuth2Provider,
|
||||
RefreshToken,
|
||||
)
|
||||
from authentik.providers.oauth2.views.token import TokenParams
|
||||
|
||||
|
||||
class TestViewsToken(TestCase):
|
||||
"""Test token view"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
self.factory = RequestFactory()
|
||||
|
||||
def test_request_auth_code(self):
|
||||
"""test request param"""
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id=generate_client_id(),
|
||||
client_secret=generate_client_secret(),
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
header = b64encode(
|
||||
f"{provider.client_id}:{provider.client_secret}".encode()
|
||||
).decode()
|
||||
user = User.objects.get(username="akadmin")
|
||||
code = AuthorizationCode.objects.create(
|
||||
code="foobar", provider=provider, user=user
|
||||
)
|
||||
request = self.factory.post(
|
||||
"/",
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
"code": code.code,
|
||||
"redirect_uri": "http://local.invalid",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
params = TokenParams.from_request(request)
|
||||
self.assertEqual(params.provider, provider)
|
||||
|
||||
def test_request_refresh_token(self):
|
||||
"""test request param"""
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id=generate_client_id(),
|
||||
client_secret=generate_client_secret(),
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
header = b64encode(
|
||||
f"{provider.client_id}:{provider.client_secret}".encode()
|
||||
).decode()
|
||||
user = User.objects.get(username="akadmin")
|
||||
token: RefreshToken = RefreshToken.objects.create(
|
||||
provider=provider,
|
||||
user=user,
|
||||
refresh_token=generate_client_id(),
|
||||
)
|
||||
request = self.factory.post(
|
||||
"/",
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_REFRESH_TOKEN,
|
||||
"refresh_token": token.refresh_token,
|
||||
"redirect_uri": "http://local.invalid",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
params = TokenParams.from_request(request)
|
||||
self.assertEqual(params.provider, provider)
|
||||
|
||||
def test_auth_code_view(self):
|
||||
"""test request param"""
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id=generate_client_id(),
|
||||
client_secret=generate_client_secret(),
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
header = b64encode(
|
||||
f"{provider.client_id}:{provider.client_secret}".encode()
|
||||
).decode()
|
||||
user = User.objects.get(username="akadmin")
|
||||
code = AuthorizationCode.objects.create(
|
||||
code="foobar", provider=provider, user=user
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
"code": code.code,
|
||||
"redirect_uri": "http://local.invalid",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
new_token: RefreshToken = RefreshToken.objects.filter(user=user).first()
|
||||
self.assertJSONEqual(
|
||||
force_str(response.content),
|
||||
{
|
||||
"access_token": new_token.access_token,
|
||||
"refresh_token": new_token.refresh_token,
|
||||
"token_type": "bearer",
|
||||
"expires_in": 600,
|
||||
"id_token": provider.encode(
|
||||
new_token.id_token.to_dict(),
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
def test_refresh_token_view(self):
|
||||
"""test request param"""
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name="test",
|
||||
client_id=generate_client_id(),
|
||||
client_secret=generate_client_secret(),
|
||||
authorization_flow=Flow.objects.first(),
|
||||
redirect_uris="http://local.invalid",
|
||||
)
|
||||
header = b64encode(
|
||||
f"{provider.client_id}:{provider.client_secret}".encode()
|
||||
).decode()
|
||||
user = User.objects.get(username="akadmin")
|
||||
token: RefreshToken = RefreshToken.objects.create(
|
||||
provider=provider,
|
||||
user=user,
|
||||
refresh_token=generate_client_id(),
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_REFRESH_TOKEN,
|
||||
"refresh_token": token.refresh_token,
|
||||
"redirect_uri": "http://local.invalid",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
new_token: RefreshToken = (
|
||||
RefreshToken.objects.filter(user=user).exclude(pk=token.pk).first()
|
||||
)
|
||||
self.assertJSONEqual(
|
||||
force_str(response.content),
|
||||
{
|
||||
"access_token": new_token.access_token,
|
||||
"refresh_token": new_token.refresh_token,
|
||||
"token_type": "bearer",
|
||||
"expires_in": 600,
|
||||
"id_token": provider.encode(
|
||||
new_token.id_token.to_dict(),
|
||||
),
|
||||
},
|
||||
)
|
@ -3,6 +3,7 @@ import re
|
||||
from base64 import b64decode
|
||||
from binascii import Error
|
||||
from typing import Optional
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse
|
||||
from django.utils.cache import patch_vary_headers
|
||||
@ -25,15 +26,34 @@ class TokenResponse(JsonResponse):
|
||||
self["Pragma"] = "no-cache"
|
||||
|
||||
|
||||
def cors_allow_any(request, response):
|
||||
"""
|
||||
Add headers to permit CORS requests from any origin, with or without credentials,
|
||||
with any headers.
|
||||
"""
|
||||
def cors_allow_any(request: HttpRequest, response: HttpResponse, *allowed_origins: str):
|
||||
"""Add headers to permit CORS requests from any origin, with or without credentials,
|
||||
with any headers."""
|
||||
origin = request.META.get("HTTP_ORIGIN")
|
||||
if not origin:
|
||||
return response
|
||||
|
||||
# OPTIONS requests don't have an authorization header -> hence
|
||||
# we can't extract the provider this request is for
|
||||
# so for options requests we allow the calling origin without checking
|
||||
allowed = request.method == "OPTIONS"
|
||||
received_origin = urlparse(origin)
|
||||
for allowed_origin in allowed_origins:
|
||||
url = urlparse(allowed_origin)
|
||||
if (
|
||||
received_origin.scheme == url.scheme
|
||||
and received_origin.hostname == url.hostname
|
||||
and received_origin.port == url.port
|
||||
):
|
||||
allowed = True
|
||||
if not allowed:
|
||||
LOGGER.warning(
|
||||
"CORS: Origin is not an allowed origin",
|
||||
requested=origin,
|
||||
allowed=allowed_origins,
|
||||
)
|
||||
return response
|
||||
|
||||
# From the CORS spec: The string "*" cannot be used for a resource that supports credentials.
|
||||
response["Access-Control-Allow-Origin"] = origin
|
||||
patch_vary_headers(response, ["Origin"])
|
||||
|
@ -6,7 +6,7 @@ from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit
|
||||
from uuid import uuid4
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.http.response import Http404, HttpResponseRedirect
|
||||
from django.http.response import Http404, HttpResponseBadRequest, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
@ -236,6 +236,9 @@ class OAuthFulfillmentStage(StageView):
|
||||
# pylint: disable=unused-argument
|
||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
"""final Stage of an OAuth2 Flow"""
|
||||
if PLAN_CONTEXT_PARAMS not in self.executor.plan.context:
|
||||
LOGGER.warning("Got to fulfillment stage with no pending context")
|
||||
return HttpResponseBadRequest()
|
||||
self.params: OAuthAuthorizationParams = self.executor.plan.context.pop(
|
||||
PLAN_CONTEXT_PARAMS
|
||||
)
|
||||
|
@ -30,6 +30,8 @@ PLAN_CONTEXT_SCOPES = "scopes"
|
||||
class ProviderInfoView(View):
|
||||
"""OpenID-compliant Provider Info"""
|
||||
|
||||
provider: OAuth2Provider
|
||||
|
||||
def get_info(self, provider: OAuth2Provider) -> dict[str, Any]:
|
||||
"""Get dictionary for OpenID Connect information"""
|
||||
scopes = list(
|
||||
@ -95,19 +97,20 @@ class ProviderInfoView(View):
|
||||
}
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get(
|
||||
self, request: HttpRequest, application_slug: str, *args, **kwargs
|
||||
) -> HttpResponse:
|
||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
"""OpenID-compliant Provider Info"""
|
||||
return JsonResponse(
|
||||
self.get_info(self.provider), json_dumps_params={"indent": 2}
|
||||
)
|
||||
|
||||
def dispatch(
|
||||
self, request: HttpRequest, application_slug: str, *args: Any, **kwargs: Any
|
||||
) -> HttpResponse:
|
||||
# Since this view only supports get, we can statically set the CORS headers
|
||||
application = get_object_or_404(Application, slug=application_slug)
|
||||
provider: OAuth2Provider = get_object_or_404(
|
||||
self.provider: OAuth2Provider = get_object_or_404(
|
||||
OAuth2Provider, pk=application.provider_id
|
||||
)
|
||||
return JsonResponse(self.get_info(provider), json_dumps_params={"indent": 2})
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
|
||||
# Since this view only supports get, we can statically set the CORS headers
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
cors_allow_any(request, response)
|
||||
cors_allow_any(request, response, *self.provider.redirect_uris.split("\n"))
|
||||
return response
|
||||
|
@ -198,7 +198,7 @@ class TokenView(View):
|
||||
response_dict = {
|
||||
"access_token": refresh_token.access_token,
|
||||
"refresh_token": refresh_token.refresh_token,
|
||||
"token_type": "Bearer",
|
||||
"token_type": "bearer",
|
||||
"expires_in": timedelta_from_string(
|
||||
self.params.provider.token_validity
|
||||
).seconds,
|
||||
|
@ -1,7 +1,8 @@
|
||||
"""authentik OAuth2 OpenID Userinfo views"""
|
||||
from typing import Any
|
||||
from typing import Any, Optional
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.http.response import HttpResponseBadRequest
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views import View
|
||||
from structlog.stdlib import get_logger
|
||||
@ -22,6 +23,8 @@ class UserInfoView(View):
|
||||
"""Create a dictionary with all the requested claims about the End-User.
|
||||
See: http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse"""
|
||||
|
||||
token: Optional[RefreshToken]
|
||||
|
||||
def get_scope_descriptions(self, scopes: list[str]) -> list[dict[str, str]]:
|
||||
"""Get a list of all Scopes's descriptions"""
|
||||
scope_descriptions = []
|
||||
@ -79,16 +82,25 @@ class UserInfoView(View):
|
||||
final_claims.update(value)
|
||||
return final_claims
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
|
||||
self.token = kwargs.get("token", None)
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
allowed_origins = []
|
||||
if self.token:
|
||||
allowed_origins = self.token.provider.redirect_uris.split("\n")
|
||||
cors_allow_any(self.request, response, *allowed_origins)
|
||||
return response
|
||||
|
||||
def options(self, request: HttpRequest) -> HttpResponse:
|
||||
return cors_allow_any(self.request, TokenResponse({}))
|
||||
return TokenResponse({})
|
||||
|
||||
def get(self, request: HttpRequest, **kwargs) -> HttpResponse:
|
||||
"""Handle GET Requests for UserInfo"""
|
||||
token: RefreshToken = kwargs["token"]
|
||||
claims = self.get_claims(token)
|
||||
claims["sub"] = token.id_token.sub
|
||||
if not self.token:
|
||||
return HttpResponseBadRequest()
|
||||
claims = self.get_claims(self.token)
|
||||
claims["sub"] = self.token.id_token.sub
|
||||
response = TokenResponse(claims)
|
||||
cors_allow_any(self.request, response)
|
||||
return response
|
||||
|
||||
def post(self, request: HttpRequest, **kwargs) -> HttpResponse:
|
||||
|
@ -21,7 +21,7 @@ class ProxyScopeMappingManager(ObjectManager):
|
||||
EnsureExists(
|
||||
ScopeMapping,
|
||||
"goauthentik.io/providers/proxy/scope-proxy",
|
||||
name="authentik default OAuth Mapping: proxy outpost",
|
||||
name="authentik default OAuth Mapping: Proxy outpost",
|
||||
scope_name=SCOPE_AK_PROXY,
|
||||
expression=SCOPE_AK_PROXY_EXPRESSION,
|
||||
),
|
||||
|
@ -1,13 +1,12 @@
|
||||
"""Channels Messages storage"""
|
||||
from asgiref.sync import async_to_sync
|
||||
from channels.layers import get_channel_layer
|
||||
from django.contrib.messages.storage.base import Message
|
||||
from django.contrib.messages.storage.fallback import FallbackStorage
|
||||
from django.contrib.messages.storage.base import BaseStorage, Message
|
||||
from django.core.cache import cache
|
||||
from django.http.request import HttpRequest
|
||||
|
||||
|
||||
class ChannelsStorage(FallbackStorage):
|
||||
class ChannelsStorage(BaseStorage):
|
||||
"""Send contrib.messages over websocket"""
|
||||
|
||||
def __init__(self, request: HttpRequest) -> None:
|
||||
@ -15,6 +14,9 @@ class ChannelsStorage(FallbackStorage):
|
||||
super().__init__(request)
|
||||
self.channel = get_channel_layer()
|
||||
|
||||
def _get(self):
|
||||
return [], True
|
||||
|
||||
def _store(self, messages: list[Message], response, *args, **kwargs):
|
||||
prefix = f"user_{self.request.session.session_key}_messages_"
|
||||
keys = cache.keys(f"{prefix}*")
|
||||
|
@ -254,8 +254,8 @@ EMAIL_HOST = CONFIG.y("email.host")
|
||||
EMAIL_PORT = int(CONFIG.y("email.port"))
|
||||
EMAIL_HOST_USER = CONFIG.y("email.username")
|
||||
EMAIL_HOST_PASSWORD = CONFIG.y("email.password")
|
||||
EMAIL_USE_TLS = CONFIG.y("email.use_tls")
|
||||
EMAIL_USE_SSL = CONFIG.y("email.use_ssl")
|
||||
EMAIL_USE_TLS = CONFIG.y_bool("email.use_tls", True)
|
||||
EMAIL_USE_SSL = CONFIG.y_bool("email.use_ssl", False)
|
||||
EMAIL_TIMEOUT = int(CONFIG.y("email.timeout"))
|
||||
DEFAULT_FROM_EMAIL = CONFIG.y("email.from")
|
||||
SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
||||
|
@ -1,9 +1,11 @@
|
||||
"""Sync LDAP Users and groups into authentik"""
|
||||
import ldap3
|
||||
import ldap3.core.exceptions
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.utils import IntegrityError
|
||||
|
||||
from authentik.core.models import Group
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer
|
||||
|
||||
|
||||
@ -47,14 +49,17 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||
"defaults": defaults,
|
||||
}
|
||||
)
|
||||
except IntegrityError as exc:
|
||||
self._logger.warning("Failed to create group", exc=exc)
|
||||
self._logger.warning(
|
||||
(
|
||||
"To merge new group with existing group, set the group's "
|
||||
except (IntegrityError, FieldError) as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
message=(
|
||||
f"Failed to create group: {str(exc)} "
|
||||
"To merge new group with existing group, set the groups's "
|
||||
f"Attribute '{LDAP_UNIQUENESS}' to '{uniq}'"
|
||||
)
|
||||
)
|
||||
),
|
||||
source=self._source,
|
||||
dn=group_dn,
|
||||
).save()
|
||||
else:
|
||||
self._logger.debug("Synced group", group=ak_group.name, created=created)
|
||||
group_count += 1
|
||||
|
@ -3,6 +3,7 @@ from datetime import datetime
|
||||
|
||||
import ldap3
|
||||
import ldap3.core.exceptions
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.utils import IntegrityError
|
||||
from pytz import UTC
|
||||
|
||||
@ -48,7 +49,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||
"defaults": defaults,
|
||||
}
|
||||
)
|
||||
except IntegrityError as exc:
|
||||
except (IntegrityError, FieldError) as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
message=(
|
||||
|
@ -5,6 +5,7 @@ from rest_framework.decorators import action
|
||||
from rest_framework.fields import BooleanField, CharField, SerializerMethodField
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import ValidationError
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.core.api.sources import SourceSerializer
|
||||
@ -47,6 +48,20 @@ class OAuthSourceSerializer(SourceSerializer):
|
||||
"""Get source's type configuration"""
|
||||
return SourceTypeSerializer(instace.type).data
|
||||
|
||||
def validate(self, attrs: dict) -> dict:
|
||||
provider_type = MANAGER.find_type(attrs.get("provider_type", ""))
|
||||
for url in [
|
||||
"authorization_url",
|
||||
"access_token_url",
|
||||
"profile_url",
|
||||
]:
|
||||
if getattr(provider_type, url, None) is None:
|
||||
if url not in attrs:
|
||||
raise ValidationError(
|
||||
f"{url} is required for provider {provider_type.name}"
|
||||
)
|
||||
return attrs
|
||||
|
||||
class Meta:
|
||||
model = OAuthSource
|
||||
fields = SourceSerializer.Meta.fields + [
|
||||
|
@ -9,6 +9,7 @@ from requests.models import Response
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
|
||||
LOGGER = get_logger()
|
||||
@ -59,7 +60,16 @@ class BaseOAuthClient:
|
||||
args.update(additional)
|
||||
params = urlencode(args)
|
||||
LOGGER.info("redirect args", **args)
|
||||
return f"{self.source.authorization_url}?{params}"
|
||||
base_url = self.source.type.authorization_url
|
||||
if self.source.authorization_url:
|
||||
base_url = self.source.authorization_url
|
||||
if base_url == "":
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
source=self.source,
|
||||
message="Source has an empty authorization URL.",
|
||||
).save()
|
||||
return f"{base_url}?{params}"
|
||||
|
||||
def parse_raw_token(self, raw_token: str) -> dict[str, Any]:
|
||||
"Parse token and secret from raw token response."
|
||||
|
@ -28,9 +28,12 @@ class OAuthClient(BaseOAuthClient):
|
||||
if raw_token is not None and verifier is not None:
|
||||
token = self.parse_raw_token(raw_token)
|
||||
try:
|
||||
access_token_url: str = self.source.type.access_token_url or ""
|
||||
if self.source.access_token_url:
|
||||
access_token_url = self.source.access_token_url
|
||||
response = self.do_request(
|
||||
"post",
|
||||
self.source.access_token_url,
|
||||
access_token_url,
|
||||
token=token,
|
||||
headers=self._default_headers,
|
||||
oauth_verifier=verifier,
|
||||
@ -48,9 +51,12 @@ class OAuthClient(BaseOAuthClient):
|
||||
"Fetch the OAuth request token. Only required for OAuth 1.0."
|
||||
callback = self.request.build_absolute_uri(self.callback)
|
||||
try:
|
||||
request_token_url: str = self.source.type.request_token_url or ""
|
||||
if self.source.request_token_url:
|
||||
request_token_url = self.source.request_token_url
|
||||
response = self.do_request(
|
||||
"post",
|
||||
self.source.request_token_url,
|
||||
request_token_url,
|
||||
headers=self._default_headers,
|
||||
oauth_callback=callback,
|
||||
)
|
||||
|
@ -56,9 +56,12 @@ class OAuth2Client(BaseOAuthClient):
|
||||
LOGGER.warning("No code returned by the source")
|
||||
return None
|
||||
try:
|
||||
access_token_url = self.source.type.access_token_url or ""
|
||||
if self.source.access_token_url:
|
||||
access_token_url = self.source.access_token_url
|
||||
response = self.session.request(
|
||||
"post",
|
||||
self.source.access_token_url,
|
||||
access_token_url,
|
||||
data=args,
|
||||
headers=self._default_headers,
|
||||
)
|
||||
|
@ -0,0 +1,43 @@
|
||||
# Generated by Django 3.2 on 2021-04-16 07:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_sources_oauth", "0002_auto_20200520_1108"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="access_token_url",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="URL used by authentik to retrive tokens.",
|
||||
max_length=255,
|
||||
verbose_name="Access Token URL",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="authorization_url",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="URL the user is redirect to to conest the flow.",
|
||||
max_length=255,
|
||||
verbose_name="Authorization URL",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="profile_url",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="URL used by authentik to get user information.",
|
||||
max_length=255,
|
||||
verbose_name="Profile URL",
|
||||
),
|
||||
),
|
||||
]
|
@ -0,0 +1,79 @@
|
||||
# Generated by Django 3.2 on 2021-04-17 19:00
|
||||
from django.apps.registry import Apps
|
||||
from django.db import migrations, models
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
|
||||
def update_empty_urls(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
OAuthSource = apps.get_model("authentik_sources_oauth", "oauthsource")
|
||||
|
||||
db_alias = schema_editor.connection.alias
|
||||
|
||||
for source in OAuthSource.objects.using(db_alias).all():
|
||||
changed = False
|
||||
if source.access_token_url == "":
|
||||
source.access_token_url = None
|
||||
changed = True
|
||||
if source.authorization_url == "":
|
||||
source.authorization_url = None
|
||||
changed = True
|
||||
if source.profile_url == "":
|
||||
source.profile_url = None
|
||||
changed = True
|
||||
if source.request_token_url == "":
|
||||
source.request_token_url = None
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
source.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_sources_oauth", "0003_auto_20210416_0726"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="access_token_url",
|
||||
field=models.CharField(
|
||||
help_text="URL used by authentik to retrive tokens.",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="Access Token URL",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="authorization_url",
|
||||
field=models.CharField(
|
||||
help_text="URL the user is redirect to to conest the flow.",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="Authorization URL",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="profile_url",
|
||||
field=models.CharField(
|
||||
help_text="URL used by authentik to get user information.",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="Profile URL",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="oauthsource",
|
||||
name="request_token_url",
|
||||
field=models.CharField(
|
||||
help_text="URL used to request the initial token. This URL is only required for OAuth 1.",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="Request Token URL",
|
||||
),
|
||||
),
|
||||
migrations.RunPython(update_empty_urls),
|
||||
]
|
@ -19,7 +19,7 @@ class OAuthSource(Source):
|
||||
|
||||
provider_type = models.CharField(max_length=255)
|
||||
request_token_url = models.CharField(
|
||||
blank=True,
|
||||
null=True,
|
||||
max_length=255,
|
||||
verbose_name=_("Request Token URL"),
|
||||
help_text=_(
|
||||
@ -28,16 +28,19 @@ class OAuthSource(Source):
|
||||
)
|
||||
authorization_url = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name=_("Authorization URL"),
|
||||
help_text=_("URL the user is redirect to to conest the flow."),
|
||||
)
|
||||
access_token_url = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name=_("Access Token URL"),
|
||||
help_text=_("URL used by authentik to retrive tokens."),
|
||||
)
|
||||
profile_url = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name=_("Profile URL"),
|
||||
help_text=_("URL used by authentik to get user information."),
|
||||
)
|
||||
@ -49,7 +52,7 @@ class OAuthSource(Source):
|
||||
"""Return the provider instance for this source"""
|
||||
from authentik.sources.oauth.types.manager import MANAGER
|
||||
|
||||
return MANAGER.find_type(self)
|
||||
return MANAGER.find_type(self.provider_type)
|
||||
|
||||
@property
|
||||
def component(self) -> str:
|
||||
@ -160,6 +163,16 @@ class OpenIDOAuthSource(OAuthSource):
|
||||
verbose_name_plural = _("OpenID OAuth Sources")
|
||||
|
||||
|
||||
class PlexOAuthSource(OAuthSource):
|
||||
"""Login using plex.tv."""
|
||||
|
||||
class Meta:
|
||||
|
||||
abstract = True
|
||||
verbose_name = _("Plex OAuth Source")
|
||||
verbose_name_plural = _("Plex OAuth Sources")
|
||||
|
||||
|
||||
class UserOAuthSourceConnection(UserSourceConnection):
|
||||
"""Authorized remote OAuth provider."""
|
||||
|
||||
|
@ -9,4 +9,5 @@ AUTHENTIK_SOURCES_OAUTH_TYPES = [
|
||||
"authentik.sources.oauth.types.twitter",
|
||||
"authentik.sources.oauth.types.azure_ad",
|
||||
"authentik.sources.oauth.types.oidc",
|
||||
"authentik.sources.oauth.types.plex",
|
||||
]
|
||||
|
@ -2,6 +2,7 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.sources.oauth.api.source import OAuthSourceSerializer
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
|
||||
|
||||
@ -18,6 +19,31 @@ class TestOAuthSource(TestCase):
|
||||
consumer_key="",
|
||||
)
|
||||
|
||||
def test_api_validate(self):
|
||||
"""Test API validation"""
|
||||
self.assertTrue(
|
||||
OAuthSourceSerializer(
|
||||
data={
|
||||
"name": "foo",
|
||||
"slug": "bar",
|
||||
"provider_type": "google",
|
||||
"consumer_key": "foo",
|
||||
"consumer_secret": "foo",
|
||||
}
|
||||
).is_valid()
|
||||
)
|
||||
self.assertFalse(
|
||||
OAuthSourceSerializer(
|
||||
data={
|
||||
"name": "foo",
|
||||
"slug": "bar",
|
||||
"provider_type": "openid-connect",
|
||||
"consumer_key": "foo",
|
||||
"consumer_secret": "foo",
|
||||
}
|
||||
).is_valid()
|
||||
)
|
||||
|
||||
def test_source_redirect(self):
|
||||
"""test redirect view"""
|
||||
self.client.get(
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Source type manager"""
|
||||
from enum import Enum
|
||||
from typing import TYPE_CHECKING, Callable, Optional
|
||||
from typing import Callable, Optional
|
||||
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
@ -9,9 +9,6 @@ from authentik.sources.oauth.views.redirect import OAuthRedirect
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
|
||||
|
||||
class RequestKind(Enum):
|
||||
"""Enum of OAuth Request types"""
|
||||
@ -58,24 +55,24 @@ class SourceTypeManager:
|
||||
"""Get list of tuples of all registered names"""
|
||||
return [(x.slug, x.name) for x in self.__sources]
|
||||
|
||||
def find_type(self, source: "OAuthSource") -> SourceType:
|
||||
def find_type(self, type_name: str) -> SourceType:
|
||||
"""Find type based on source"""
|
||||
found_type = None
|
||||
for src_type in self.__sources:
|
||||
if src_type.slug == source.provider_type:
|
||||
if src_type.slug == type_name:
|
||||
return src_type
|
||||
if not found_type:
|
||||
found_type = SourceType()
|
||||
LOGGER.warning(
|
||||
"no matching type found, using default",
|
||||
wanted=source.provider_type,
|
||||
have=[x.name for x in self.__sources],
|
||||
wanted=type_name,
|
||||
have=[x.slug for x in self.__sources],
|
||||
)
|
||||
return found_type
|
||||
|
||||
def find(self, source: "OAuthSource", kind: RequestKind) -> Callable:
|
||||
def find(self, type_name: str, kind: RequestKind) -> Callable:
|
||||
"""Find fitting Source Type"""
|
||||
found_type = self.find_type(source)
|
||||
found_type = self.find_type(type_name)
|
||||
if kind == RequestKind.CALLBACK:
|
||||
return found_type.callback_view
|
||||
if kind == RequestKind.REDIRECT:
|
||||
|
134
authentik/sources/oauth/types/plex.py
Normal file
134
authentik/sources/oauth/types/plex.py
Normal file
@ -0,0 +1,134 @@
|
||||
"""Plex OAuth Views"""
|
||||
from typing import Any, Optional
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.http.response import Http404
|
||||
from requests import post
|
||||
from requests.api import get
|
||||
from requests.exceptions import RequestException
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import __version__
|
||||
from authentik.sources.oauth.clients.oauth2 import OAuth2Client
|
||||
from authentik.sources.oauth.models import OAuthSource, UserOAuthSourceConnection
|
||||
from authentik.sources.oauth.types.manager import MANAGER, SourceType
|
||||
from authentik.sources.oauth.views.callback import OAuthCallback
|
||||
from authentik.sources.oauth.views.redirect import OAuthRedirect
|
||||
|
||||
LOGGER = get_logger()
|
||||
SESSION_ID_KEY = "PLEX_ID"
|
||||
SESSION_CODE_KEY = "PLEX_CODE"
|
||||
DEFAULT_PAYLOAD = {
|
||||
"X-Plex-Product": "authentik",
|
||||
"X-Plex-Version": __version__,
|
||||
"X-Plex-Device-Vendor": "BeryJu.org",
|
||||
}
|
||||
|
||||
|
||||
class PlexRedirect(OAuthRedirect):
|
||||
"""Plex Auth redirect, get a pin then redirect to a URL to claim it"""
|
||||
|
||||
headers = {}
|
||||
|
||||
def get_pin(self, **data) -> dict:
|
||||
"""Get plex pin that the user will claim
|
||||
https://forums.plex.tv/t/authenticating-with-plex/609370"""
|
||||
return post(
|
||||
"https://plex.tv/api/v2/pins.json?strong=true",
|
||||
data=data,
|
||||
headers=self.headers,
|
||||
).json()
|
||||
|
||||
def get_redirect_url(self, **kwargs) -> str:
|
||||
slug = kwargs.get("source_slug", "")
|
||||
self.headers = {"Origin": self.request.build_absolute_uri("/")}
|
||||
try:
|
||||
source: OAuthSource = OAuthSource.objects.get(slug=slug)
|
||||
except OAuthSource.DoesNotExist:
|
||||
raise Http404(f"Unknown OAuth source '{slug}'.")
|
||||
else:
|
||||
payload = DEFAULT_PAYLOAD.copy()
|
||||
payload["X-Plex-Client-Identifier"] = source.consumer_key
|
||||
# Get a pin first
|
||||
pin = self.get_pin(**payload)
|
||||
LOGGER.debug("Got pin", **pin)
|
||||
self.request.session[SESSION_ID_KEY] = pin["id"]
|
||||
self.request.session[SESSION_CODE_KEY] = pin["code"]
|
||||
qs = {
|
||||
"clientID": source.consumer_key,
|
||||
"code": pin["code"],
|
||||
"forwardUrl": self.request.build_absolute_uri(
|
||||
self.get_callback_url(source)
|
||||
),
|
||||
}
|
||||
return f"https://app.plex.tv/auth#!?{urlencode(qs)}"
|
||||
|
||||
|
||||
class PlexOAuthClient(OAuth2Client):
|
||||
"""Retrive the plex token after authentication, then ask the plex API about user info"""
|
||||
|
||||
def check_application_state(self) -> bool:
|
||||
return SESSION_ID_KEY in self.request.session
|
||||
|
||||
def get_access_token(self, **request_kwargs) -> Optional[dict[str, Any]]:
|
||||
payload = dict(DEFAULT_PAYLOAD)
|
||||
payload["X-Plex-Client-Identifier"] = self.source.consumer_key
|
||||
payload["Accept"] = "application/json"
|
||||
response = get(
|
||||
f"https://plex.tv/api/v2/pins/{self.request.session[SESSION_ID_KEY]}",
|
||||
headers=payload,
|
||||
)
|
||||
response.raise_for_status()
|
||||
token = response.json()["authToken"]
|
||||
return {"plex_token": token}
|
||||
|
||||
def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]:
|
||||
"Fetch user profile information."
|
||||
qs = {"X-Plex-Token": token["plex_token"]}
|
||||
try:
|
||||
response = self.do_request(
|
||||
"get", f"https://plex.tv/users/account.json?{urlencode(qs)}"
|
||||
)
|
||||
response.raise_for_status()
|
||||
except RequestException as exc:
|
||||
LOGGER.warning("Unable to fetch user profile", exc=exc)
|
||||
return None
|
||||
else:
|
||||
return response.json().get("user", {})
|
||||
|
||||
|
||||
class PlexOAuth2Callback(OAuthCallback):
|
||||
"""Plex OAuth2 Callback"""
|
||||
|
||||
client_class = PlexOAuthClient
|
||||
|
||||
def get_user_id(
|
||||
self, source: UserOAuthSourceConnection, info: dict[str, Any]
|
||||
) -> Optional[str]:
|
||||
return info.get("uuid")
|
||||
|
||||
def get_user_enroll_context(
|
||||
self,
|
||||
source: OAuthSource,
|
||||
access: UserOAuthSourceConnection,
|
||||
info: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"username": info.get("username"),
|
||||
"email": info.get("email"),
|
||||
"name": info.get("title"),
|
||||
}
|
||||
|
||||
|
||||
@MANAGER.type()
|
||||
class PlexType(SourceType):
|
||||
"""Plex Type definition"""
|
||||
|
||||
redirect_view = PlexRedirect
|
||||
callback_view = PlexOAuth2Callback
|
||||
name = "Plex"
|
||||
slug = "plex"
|
||||
|
||||
authorization_url = ""
|
||||
access_token_url = "" # nosec
|
||||
profile_url = ""
|
@ -209,9 +209,9 @@ class OAuthCallback(OAuthClientMixin, View):
|
||||
)
|
||||
return redirect(
|
||||
reverse(
|
||||
"authentik_sources_oauth:oauth-client-user",
|
||||
kwargs={"source_slug": self.source.slug},
|
||||
"authentik_core:if-admin",
|
||||
)
|
||||
+ f"#/user;page-{self.source.slug}"
|
||||
)
|
||||
|
||||
def handle_enroll(
|
||||
|
@ -21,6 +21,6 @@ class DispatcherView(View):
|
||||
if not slug:
|
||||
raise Http404
|
||||
source = get_object_or_404(OAuthSource, slug=slug)
|
||||
view = MANAGER.find(source, kind=RequestKind(self.kind))
|
||||
view = MANAGER.find(source.provider_type, kind=RequestKind(self.kind))
|
||||
LOGGER.debug("dispatching OAuth2 request to", view=view, kind=self.kind)
|
||||
return view.as_view()(*args, **kwargs)
|
||||
|
@ -63,6 +63,7 @@ class EmailStageViewSet(ModelViewSet):
|
||||
"name": value,
|
||||
"description": label,
|
||||
"component": "",
|
||||
"model_name": "",
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(choices, many=True).data)
|
||||
|
@ -4,6 +4,7 @@ version: '3.2'
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:12
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- database:/var/lib/postgresql/data
|
||||
networks:
|
||||
@ -19,7 +20,8 @@ services:
|
||||
networks:
|
||||
- internal
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.1}
|
||||
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.3}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
@ -46,7 +48,8 @@ services:
|
||||
env_file:
|
||||
- .env
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.1}
|
||||
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.3}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
networks:
|
||||
- internal
|
||||
@ -65,7 +68,8 @@ services:
|
||||
env_file:
|
||||
- .env
|
||||
static:
|
||||
image: ${AUTHENTIK_IMAGE_STATIC:-beryju/authentik-static}:${AUTHENTIK_TAG:-2021.4.1}
|
||||
image: ${AUTHENTIK_IMAGE_STATIC:-beryju/authentik-static}:${AUTHENTIK_TAG:-2021.4.3}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- internal
|
||||
labels:
|
||||
@ -74,13 +78,14 @@ services:
|
||||
traefik.http.routers.static-router.rule: PathPrefix(`/static`, `/if`, `/media`, `/robots.txt`, `/favicon.ico`)
|
||||
traefik.http.routers.static-router.tls: 'true'
|
||||
traefik.http.routers.static-router.service: static-service
|
||||
traefik.http.services.static-service.loadbalancer.healthcheck.path: /-/health/ready/
|
||||
traefik.http.services.static-service.loadbalancer.healthcheck.path: /
|
||||
traefik.http.services.static-service.loadbalancer.healthcheck.interval: 30s
|
||||
traefik.http.services.static-service.loadbalancer.server.port: '80'
|
||||
volumes:
|
||||
- ./media:/usr/share/nginx/html/media
|
||||
traefik:
|
||||
image: traefik:2.3
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "--log.format=json"
|
||||
- "--api.insecure=true"
|
||||
|
@ -4,7 +4,7 @@ name: authentik
|
||||
home: https://goauthentik.io
|
||||
sources:
|
||||
- https://github.com/BeryJu/authentik
|
||||
version: "2021.4.1"
|
||||
version: "2021.4.3"
|
||||
icon: https://raw.githubusercontent.com/BeryJu/authentik/master/web/icons/icon.svg
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
|
@ -4,12 +4,12 @@
|
||||
|-----------------------------------|-------------------------|-------------|
|
||||
| image.name | beryju/authentik | Image used to run the authentik server and worker |
|
||||
| image.name_static | beryju/authentik-static | Image used to run the authentik static server (CSS and JS Files) |
|
||||
| image.tag | 2021.4.1 | Image tag |
|
||||
| image.tag | 2021.4.3 | Image tag |
|
||||
| image.pullPolicy | IfNotPresent | Image Pull Policy used for all deployments |
|
||||
| serverReplicas | 1 | Replicas for the Server deployment |
|
||||
| workerReplicas | 1 | Replicas for the Worker deployment |
|
||||
| kubernetesIntegration | true | Enable/disable the Kubernetes integration for authentik. This will create a service account for authentik to create and update outposts in authentik |
|
||||
| config.secretKey | | Secret key used to sign session cookies, generate with `pwgen 50 1` for example. |
|
||||
| config.secretKey | | Secret key used to sign session cookies, generate with `pwgen 50 1` or `openssl rand -base64 36` for example. |
|
||||
| config.errorReporting.enabled | false | Enable/disable error reporting |
|
||||
| config.errorReporting.environment | customer | Environment sent with the error reporting |
|
||||
| config.errorReporting.sendPii | false | Whether to send Personally-identifiable data with the error reporting |
|
||||
@ -22,6 +22,11 @@
|
||||
| config.email.use_ssl | false | Enable SSL |
|
||||
| config.email.timeout | 10 | SMTP Timeout |
|
||||
| config.email.from | authentik@localhost | Email address authentik will send from, should have a correct @domain |
|
||||
| pvc.mode | ReadWriteMany | Mode that the PVCs are created in (uploads and GeoIP, if enabled) |
|
||||
| pvc.uploadsSize | 5Gi | Size for the uploads PVC |
|
||||
| pvc.uploadsStorageClass | null | Storage class for the uploads PVC (default: use default storage class) |
|
||||
| pvc.geoIpSize | 1Gi | Size for the GeoIP PVC |
|
||||
| pvc.geoIpStorageClass | null | Storage class for the GeoIP PVC (default: use default storage class) |
|
||||
| geoip.enabled | false | Optionally enable GeoIP |
|
||||
| geoip.accountId | | GeoIP MaxMind Account ID |
|
||||
| geoip.licenseKey | | GeoIP MaxMind License key |
|
||||
|
@ -10,8 +10,9 @@ metadata:
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
- {{ .Values.pvc.mode }}
|
||||
storageClassName: {{ .Values.pvc.geoIpStorageClass }}
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storage: {{ .Values.pvc.geoIpSize }}
|
||||
{{- end }}
|
||||
|
@ -9,7 +9,8 @@ metadata:
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
- {{ .Values.pvc.mode }}
|
||||
storageClassName: {{ .Values.pvc.uploadsStorageClass }}
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
storage: {{ .Values.pvc.uploadsSize }}
|
||||
|
@ -43,29 +43,6 @@ spec:
|
||||
values:
|
||||
- web
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
initContainers:
|
||||
- name: authentik-database-migrations
|
||||
image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||
args: [migrate]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: {{ include "authentik.fullname" . }}-config
|
||||
prefix: AUTHENTIK_
|
||||
- secretRef:
|
||||
name: {{ include "authentik.fullname" . }}-secret-key
|
||||
prefix: AUTHENTIK_
|
||||
env:
|
||||
- name: AUTHENTIK_REDIS__PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: "{{ .Release.Name }}-redis"
|
||||
key: redis-password
|
||||
- name: AUTHENTIK_POSTGRESQL__PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: "{{ .Release.Name }}-postgresql"
|
||||
key: postgresql-password
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
|
||||
|
@ -5,7 +5,7 @@ image:
|
||||
name: beryju/authentik
|
||||
name_static: beryju/authentik-static
|
||||
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
|
||||
tag: 2021.4.1
|
||||
tag: 2021.4.3
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
serverReplicas: 1
|
||||
@ -15,7 +15,14 @@ workerReplicas: 1
|
||||
kubernetesIntegration: true
|
||||
|
||||
monitoring:
|
||||
enabled: true
|
||||
enabled: false
|
||||
|
||||
pvc:
|
||||
mode: ReadWriteMany
|
||||
uploadsSize: 5Gi
|
||||
uploadsStorageClass: null
|
||||
geoIpSize: 1Gi
|
||||
geoIpStorageClass: null
|
||||
|
||||
config:
|
||||
# Optionally specify fixed secret_key, otherwise generated automatically
|
||||
|
@ -2,13 +2,13 @@
|
||||
python -m lifecycle.wait_for_db
|
||||
printf '{"event": "Bootstrap completed", "level": "info", "logger": "bootstrap", "command": "%s"}\n' "$@" > /dev/stderr
|
||||
if [[ "$1" == "server" ]]; then
|
||||
python -m lifecycle.migrate
|
||||
gunicorn -c /lifecycle/gunicorn.conf.py authentik.root.asgi:application
|
||||
elif [[ "$1" == "worker" ]]; then
|
||||
celery -A authentik.root.celery worker --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events
|
||||
elif [[ "$1" == "migrate" ]]; then
|
||||
# Run system migrations first, run normal migrations after
|
||||
printf "DEPERECATED: database migrations are now executed automatically on startup."
|
||||
python -m lifecycle.migrate
|
||||
python -m manage migrate
|
||||
elif [[ "$1" == "backup" ]]; then
|
||||
python -m manage dbbackup --clean
|
||||
elif [[ "$1" == "restore" ]]; then
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
"""System Migration handler"""
|
||||
import os
|
||||
from importlib.util import module_from_spec, spec_from_file_location
|
||||
from inspect import getmembers, isclass
|
||||
from pathlib import Path
|
||||
@ -11,6 +12,7 @@ from structlog.stdlib import get_logger
|
||||
from authentik.lib.config import CONFIG
|
||||
|
||||
LOGGER = get_logger()
|
||||
ADV_LOCK_UID = 1000
|
||||
|
||||
|
||||
class BaseMigration:
|
||||
@ -40,18 +42,36 @@ if __name__ == "__main__":
|
||||
host=CONFIG.y("postgresql.host"),
|
||||
)
|
||||
curr = conn.cursor()
|
||||
# lock an advisory lock to prevent multiple instances from migrating at once
|
||||
LOGGER.info("waiting to acquire database lock")
|
||||
curr.execute("SELECT pg_advisory_lock(%s)", (ADV_LOCK_UID,))
|
||||
try:
|
||||
for migration in (
|
||||
Path(__file__).parent.absolute().glob("system_migrations/*.py")
|
||||
):
|
||||
spec = spec_from_file_location("lifecycle.system_migrations", migration)
|
||||
mod = module_from_spec(spec)
|
||||
# pyright: reportGeneralTypeIssues=false
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
for migration in Path(__file__).parent.absolute().glob("system_migrations/*.py"):
|
||||
spec = spec_from_file_location("lifecycle.system_migrations", migration)
|
||||
mod = module_from_spec(spec)
|
||||
# pyright: reportGeneralTypeIssues=false
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
for name, sub in getmembers(mod, isclass):
|
||||
if name != "Migration":
|
||||
continue
|
||||
migration = sub(curr, conn)
|
||||
if migration.needs_migration():
|
||||
LOGGER.info("Migration needs to be applied", migration=sub)
|
||||
migration.run()
|
||||
LOGGER.info("Migration finished applying", migration=sub)
|
||||
for name, sub in getmembers(mod, isclass):
|
||||
if name != "Migration":
|
||||
continue
|
||||
migration = sub(curr, conn)
|
||||
if migration.needs_migration():
|
||||
LOGGER.info("Migration needs to be applied", migration=sub)
|
||||
migration.run()
|
||||
LOGGER.info("Migration finished applying", migration=sub)
|
||||
LOGGER.info("applying django migrations")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(["", "migrate"])
|
||||
finally:
|
||||
curr.execute("SELECT pg_advisory_unlock(%s)", (ADV_LOCK_UID,))
|
||||
|
@ -18,7 +18,7 @@ stages:
|
||||
steps:
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.15'
|
||||
version: '1.16.3'
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: |
|
||||
@ -40,11 +40,7 @@ stages:
|
||||
steps:
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.15'
|
||||
- task: Go@0
|
||||
inputs:
|
||||
command: 'get'
|
||||
arguments: '-u golang.org/x/lint/golint'
|
||||
version: '1.16.3'
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
@ -53,7 +49,7 @@ stages:
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: |
|
||||
$(go list -f {{.Target}} golang.org/x/lint/golint) ./...
|
||||
docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.39.0 golangci-lint run -v --timeout 200s
|
||||
workingDirectory: 'outpost/'
|
||||
- stage: proxy_build_go
|
||||
jobs:
|
||||
@ -63,7 +59,7 @@ stages:
|
||||
steps:
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.15'
|
||||
version: '1.16.3'
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
@ -82,7 +78,7 @@ stages:
|
||||
steps:
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.15'
|
||||
version: '1.16.3'
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
|
@ -52,13 +52,14 @@ func main() {
|
||||
|
||||
ac.Server = proxy.NewServer(ac)
|
||||
|
||||
ac.Start()
|
||||
err = ac.Start()
|
||||
if err != nil {
|
||||
log.WithError(err).Panic("Failed to run server")
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-interrupt:
|
||||
ac.Shutdown()
|
||||
os.Exit(0)
|
||||
}
|
||||
<-interrupt
|
||||
ac.Shutdown()
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ require (
|
||||
github.com/getsentry/sentry-go v0.10.0
|
||||
github.com/go-openapi/analysis v0.20.1 // indirect
|
||||
github.com/go-openapi/errors v0.20.0
|
||||
github.com/go-openapi/runtime v0.19.27
|
||||
github.com/go-openapi/runtime v0.19.28
|
||||
github.com/go-openapi/strfmt v0.20.1
|
||||
github.com/go-openapi/swag v0.19.15
|
||||
github.com/go-openapi/validate v0.20.2
|
||||
github.com/go-redis/redis/v7 v7.4.0 // indirect
|
||||
github.com/go-swagger/go-swagger v0.27.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
|
||||
github.com/justinas/alice v1.2.0
|
||||
@ -23,6 +23,7 @@ require (
|
||||
github.com/oauth2-proxy/oauth2-proxy v0.0.0-20200831161845-e4e5580852dc
|
||||
github.com/pelletier/go-toml v1.9.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect
|
||||
github.com/recws-org/recws v1.3.1
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
@ -30,10 +31,11 @@ require (
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.7.1 // indirect
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 // indirect
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
|
||||
golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
|
||||
golang.org/x/sys v0.0.0-20210415045647-66c3f260301c // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/grpc v1.31.0 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
)
|
||||
|
@ -102,7 +102,6 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -124,8 +123,6 @@ github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHj
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
|
||||
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
@ -157,7 +154,6 @@ github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9sn
|
||||
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
|
||||
github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ=
|
||||
github.com/go-openapi/analysis v0.19.16/go.mod h1:GLInF007N83Ad3m8a/CbQ5TPzdnGT7workfHwuVjNVk=
|
||||
github.com/go-openapi/analysis v0.20.0 h1:UN09o0kNhleunxW7LR+KnltD0YrJ8FF03pSqvAN3Vro=
|
||||
github.com/go-openapi/analysis v0.20.0/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og=
|
||||
github.com/go-openapi/analysis v0.20.1 h1:zdVbw8yoD4SWZeq+cWdGgquaB0W4VrsJvDJHJND/Ktc=
|
||||
github.com/go-openapi/analysis v0.20.1/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og=
|
||||
@ -171,8 +167,6 @@ github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpX
|
||||
github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.20.0 h1:Sxpo9PjEHDzhs3FbnGNonvDgWcMW2U7wGTcDDSFSceM=
|
||||
github.com/go-openapi/errors v0.20.0/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
|
||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
|
||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
@ -202,8 +196,8 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g
|
||||
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
|
||||
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
|
||||
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
|
||||
github.com/go-openapi/runtime v0.19.27 h1:4zrQCJoP7rqNCUaApDv1MdPkaa5TuPfO05Lq5WLhX9I=
|
||||
github.com/go-openapi/runtime v0.19.27/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
|
||||
github.com/go-openapi/runtime v0.19.28 h1:9lYu6axek8LJrVkMVViVirRcpoaCxXX7+sSvmizGVnA=
|
||||
github.com/go-openapi/runtime v0.19.28/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
|
||||
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
|
||||
@ -252,9 +246,6 @@ github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRf
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-swagger/go-swagger v0.27.0 h1:K7+nkBuf4oS1jTBrdvWqYFpqD69V5CN8HamZzCDDhAI=
|
||||
github.com/go-swagger/go-swagger v0.27.0/go.mod h1:WodZVysInJilkW7e6IRw+dZGp5yW6rlMFZ4cb+THl9A=
|
||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
||||
@ -310,8 +301,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
@ -329,8 +318,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@ -352,8 +341,6 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
@ -392,8 +379,6 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
|
||||
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
|
||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
|
||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
|
||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o=
|
||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
@ -521,8 +506,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.0 h1:NOd0BRdOKpPf0SxkL3HxSQOG7rNh+4kl6PHcBPFs7Q0=
|
||||
github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
|
||||
@ -538,8 +521,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e h1:BLqxdwZ6j771IpSCRx7s/GJjXHUE00Hmu7/YegCGdzA=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac h1:jWKYCNlX4J5s8M0nHYkh7Y7c9gRVDEb3mq51j5J0F5M=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@ -559,7 +540,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
@ -586,7 +566,6 @@ github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
@ -595,7 +574,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -613,8 +591,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
|
||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
@ -649,7 +625,6 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||
github.com/yuin/gopher-lua v0.0.0-20191213034115-f46add6fdb5c/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0=
|
||||
@ -690,8 +665,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc=
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -724,8 +697,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -766,23 +737,18 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5 h1:zuP3axpB9rV3xH0EA7n3/gCrNPZm2SRl0l4mVH2BRj4=
|
||||
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 h1:4qWs8cYYH6PoEFy4dfhDFgoMGkwAcETd+MmPdCPMzUc=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d h1:BgJvlyh+UqCUaPlscHJ+PN8GcpfrFdr7NHjd1JL0+Gs=
|
||||
golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 h1:Mj83v+wSRNEar42a/MQgxk9X42TdEmrOl9i+y8WbxLo=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 h1:D7nTwh4J0i+5mW4Zjzn5omvlr6YBcWywE6KOcatyNxY=
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -794,7 +760,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -845,13 +810,9 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/sys v0.0.0-20210415045647-66c3f260301c h1:6L+uOeS3OQt/f4eFHXZcTxeZrGCuz+CLElgEBjbcTA4=
|
||||
golang.org/x/sys v0.0.0-20210415045647-66c3f260301c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -859,7 +820,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@ -919,8 +879,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -1004,7 +962,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
@ -39,8 +40,8 @@ type APIController struct {
|
||||
}
|
||||
|
||||
// NewAPIController initialise new API Controller instance from URL and API token
|
||||
func NewAPIController(pbURL url.URL, token string) *APIController {
|
||||
transport := httptransport.New(pbURL.Host, client.DefaultBasePath, []string{pbURL.Scheme})
|
||||
func NewAPIController(akURL url.URL, token string) *APIController {
|
||||
transport := httptransport.New(akURL.Host, client.DefaultBasePath, []string{akURL.Scheme})
|
||||
transport.Transport = SetUserAgent(getTLSTransport(), fmt.Sprintf("authentik-proxy@%s", pkg.VERSION))
|
||||
|
||||
// create the transport
|
||||
@ -53,10 +54,11 @@ func NewAPIController(pbURL url.URL, token string) *APIController {
|
||||
|
||||
// Because we don't know the outpost UUID, we simply do a list and pick the first
|
||||
// The service account this token belongs to should only have access to a single outpost
|
||||
outposts, err := apiClient.Outposts.OutpostsOutpostsList(outposts.NewOutpostsOutpostsListParams(), auth)
|
||||
outposts, err := apiClient.Outposts.OutpostsInstancesList(outposts.NewOutpostsInstancesListParams(), auth)
|
||||
|
||||
if err != nil {
|
||||
log.WithError(err).Panic("Failed to fetch configuration")
|
||||
log.WithError(err).Error("Failed to fetch configuration")
|
||||
os.Exit(1)
|
||||
}
|
||||
outpost := outposts.Payload.Results[0]
|
||||
doGlobalSetup(outpost.Config.(map[string]interface{}))
|
||||
@ -73,7 +75,7 @@ func NewAPIController(pbURL url.URL, token string) *APIController {
|
||||
lastBundleHash: "",
|
||||
}
|
||||
ac.logger.Debugf("HA Reload offset: %s", ac.reloadOffset)
|
||||
ac.initWS(pbURL, outpost.Pk)
|
||||
ac.initWS(akURL, outpost.Pk)
|
||||
return ac
|
||||
}
|
||||
|
||||
@ -96,7 +98,10 @@ func (a *APIController) Start() error {
|
||||
a.startWSHealth()
|
||||
}()
|
||||
go func() {
|
||||
a.Server.Start()
|
||||
err := a.Server.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
@ -64,7 +64,6 @@ func (ac *APIController) Shutdown() {
|
||||
ac.logger.Println("write close:", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ac *APIController) startWSHandler() {
|
||||
@ -92,7 +91,8 @@ func (ac *APIController) startWSHandler() {
|
||||
}
|
||||
|
||||
func (ac *APIController) startWSHealth() {
|
||||
for ; true; <-time.Tick(time.Second * 10) {
|
||||
ticker := time.NewTicker(time.Second * 10)
|
||||
for ; true; <-ticker.C {
|
||||
if !ac.wsConn.IsConnected() {
|
||||
continue
|
||||
}
|
||||
|
@ -38,7 +38,11 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
|
||||
return nil
|
||||
}
|
||||
providerOpts := &options.Options{}
|
||||
copier.Copy(&providerOpts, getCommonOptions())
|
||||
err = copier.Copy(&providerOpts, getCommonOptions())
|
||||
if err != nil {
|
||||
log.WithError(err).Warning("Failed to copy options, skipping provider")
|
||||
return nil
|
||||
}
|
||||
providerOpts.ClientID = provider.ClientID
|
||||
providerOpts.ClientSecret = provider.ClientSecret
|
||||
|
||||
@ -62,7 +66,7 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
|
||||
ID: "default",
|
||||
URI: *provider.InternalHost,
|
||||
Path: "/",
|
||||
InsecureSkipTLSVerify: *&provider.InternalHostSslValidation,
|
||||
InsecureSkipTLSVerify: provider.InternalHostSslValidation,
|
||||
},
|
||||
}
|
||||
|
||||
@ -85,7 +89,7 @@ func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *opti
|
||||
return providerOpts
|
||||
}
|
||||
|
||||
x509cert, err := tls.X509KeyPair([]byte(*&cert.Payload.Data), []byte(key.Payload.Data))
|
||||
x509cert, err := tls.X509KeyPair([]byte(cert.Payload.Data), []byte(key.Payload.Data))
|
||||
if err != nil {
|
||||
pb.log.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to parse certificate")
|
||||
return providerOpts
|
||||
@ -135,7 +139,7 @@ func (pb *providerBundle) Build(provider *models.ProxyOutpostConfig) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *&provider.BasicAuthEnabled {
|
||||
if provider.BasicAuthEnabled {
|
||||
oauthproxy.SetBasicAuth = true
|
||||
oauthproxy.BasicAuthUserAttribute = provider.BasicAuthUserAttribute
|
||||
oauthproxy.BasicAuthPasswordAttribute = provider.BasicAuthPasswordAttribute
|
||||
|
@ -1,3 +1,3 @@
|
||||
package pkg
|
||||
|
||||
const VERSION = "2021.4.1"
|
||||
const VERSION = "2021.4.3"
|
||||
|
334
swagger.yaml
334
swagger.yaml
@ -1152,6 +1152,9 @@ paths:
|
||||
description: Page Size
|
||||
required: false
|
||||
type: integer
|
||||
- name: superuser_full_list
|
||||
in: query
|
||||
type: boolean
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
@ -2237,15 +2240,15 @@ paths:
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Link'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
tags:
|
||||
- core
|
||||
parameters:
|
||||
@ -3664,15 +3667,15 @@ paths:
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Challenge'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
tags:
|
||||
- flows
|
||||
post:
|
||||
@ -4366,6 +4369,281 @@ paths:
|
||||
description: A unique integer value identifying this OAuth2 Token.
|
||||
required: true
|
||||
type: integer
|
||||
/outposts/instances/:
|
||||
get:
|
||||
operationId: outposts_instances_list
|
||||
description: Outpost Viewset
|
||||
parameters:
|
||||
- name: providers__isnull
|
||||
in: query
|
||||
description: ''
|
||||
required: false
|
||||
type: string
|
||||
- name: ordering
|
||||
in: query
|
||||
description: Which field to use when ordering the results.
|
||||
required: false
|
||||
type: string
|
||||
- name: search
|
||||
in: query
|
||||
description: A search term.
|
||||
required: false
|
||||
type: string
|
||||
- name: page
|
||||
in: query
|
||||
description: Page Index
|
||||
required: false
|
||||
type: integer
|
||||
- name: page_size
|
||||
in: query
|
||||
description: Page Size
|
||||
required: false
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
required:
|
||||
- results
|
||||
- pagination
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
required:
|
||||
- next
|
||||
- previous
|
||||
- count
|
||||
- current
|
||||
- total_pages
|
||||
- start_index
|
||||
- end_index
|
||||
type: object
|
||||
properties:
|
||||
next:
|
||||
type: number
|
||||
previous:
|
||||
type: number
|
||||
count:
|
||||
type: number
|
||||
current:
|
||||
type: number
|
||||
total_pages:
|
||||
type: number
|
||||
start_index:
|
||||
type: number
|
||||
end_index:
|
||||
type: number
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Outpost'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
tags:
|
||||
- outposts
|
||||
post:
|
||||
operationId: outposts_instances_create
|
||||
description: Outpost Viewset
|
||||
parameters:
|
||||
- name: data
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
responses:
|
||||
'201':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
'400':
|
||||
description: Invalid input.
|
||||
schema:
|
||||
$ref: '#/definitions/ValidationError'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
tags:
|
||||
- outposts
|
||||
parameters: []
|
||||
/outposts/instances/default_settings/:
|
||||
get:
|
||||
operationId: outposts_instances_default_settings
|
||||
description: Global default outpost config
|
||||
parameters:
|
||||
- name: providers__isnull
|
||||
in: query
|
||||
description: ''
|
||||
required: false
|
||||
type: string
|
||||
- name: ordering
|
||||
in: query
|
||||
description: Which field to use when ordering the results.
|
||||
required: false
|
||||
type: string
|
||||
- name: search
|
||||
in: query
|
||||
description: A search term.
|
||||
required: false
|
||||
type: string
|
||||
- name: page
|
||||
in: query
|
||||
description: Page Index
|
||||
required: false
|
||||
type: integer
|
||||
- name: page_size
|
||||
in: query
|
||||
description: Page Size
|
||||
required: false
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/OutpostDefaultConfig'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
tags:
|
||||
- outposts
|
||||
parameters: []
|
||||
/outposts/instances/{uuid}/:
|
||||
get:
|
||||
operationId: outposts_instances_read
|
||||
description: Outpost Viewset
|
||||
parameters: []
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
tags:
|
||||
- outposts
|
||||
put:
|
||||
operationId: outposts_instances_update
|
||||
description: Outpost Viewset
|
||||
parameters:
|
||||
- name: data
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
'400':
|
||||
description: Invalid input.
|
||||
schema:
|
||||
$ref: '#/definitions/ValidationError'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
tags:
|
||||
- outposts
|
||||
patch:
|
||||
operationId: outposts_instances_partial_update
|
||||
description: Outpost Viewset
|
||||
parameters:
|
||||
- name: data
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Outpost'
|
||||
'400':
|
||||
description: Invalid input.
|
||||
schema:
|
||||
$ref: '#/definitions/ValidationError'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
tags:
|
||||
- outposts
|
||||
delete:
|
||||
operationId: outposts_instances_delete
|
||||
description: Outpost Viewset
|
||||
parameters: []
|
||||
responses:
|
||||
'204':
|
||||
description: ''
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
tags:
|
||||
- outposts
|
||||
parameters:
|
||||
- name: uuid
|
||||
in: path
|
||||
description: A UUID string identifying this outpost.
|
||||
required: true
|
||||
type: string
|
||||
format: uuid
|
||||
/outposts/instances/{uuid}/health/:
|
||||
get:
|
||||
operationId: outposts_instances_health
|
||||
description: Get outposts current health
|
||||
parameters: []
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/OutpostHealth'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
'404':
|
||||
description: Object does not exist or caller has insufficient permissions
|
||||
to access it.
|
||||
schema:
|
||||
$ref: '#/definitions/APIException'
|
||||
tags:
|
||||
- outposts
|
||||
parameters:
|
||||
- name: uuid
|
||||
in: path
|
||||
description: A UUID string identifying this outpost.
|
||||
required: true
|
||||
type: string
|
||||
format: uuid
|
||||
/outposts/outposts/:
|
||||
get:
|
||||
operationId: outposts_outposts_list
|
||||
@ -7671,6 +7949,9 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/PolicyTest'
|
||||
- name: format_result
|
||||
in: query
|
||||
type: boolean
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
@ -10265,7 +10546,7 @@ paths:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/UserSetting'
|
||||
$ref: '#/definitions/StageUserSetting'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
@ -14771,6 +15052,7 @@ definitions:
|
||||
- name
|
||||
- description
|
||||
- component
|
||||
- model_name
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
@ -14785,6 +15067,10 @@ definitions:
|
||||
title: Component
|
||||
type: string
|
||||
minLength: 1
|
||||
model_name:
|
||||
title: Model name
|
||||
type: string
|
||||
minLength: 1
|
||||
EventTopPerUser:
|
||||
required:
|
||||
- application
|
||||
@ -16963,9 +17249,6 @@ definitions:
|
||||
- name
|
||||
- slug
|
||||
- provider_type
|
||||
- authorization_url
|
||||
- access_token_url
|
||||
- profile_url
|
||||
- consumer_key
|
||||
- consumer_secret
|
||||
type: object
|
||||
@ -17032,24 +17315,29 @@ definitions:
|
||||
for OAuth 1.
|
||||
type: string
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
x-nullable: true
|
||||
authorization_url:
|
||||
title: Authorization URL
|
||||
description: URL the user is redirect to to conest the flow.
|
||||
type: string
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
x-nullable: true
|
||||
access_token_url:
|
||||
title: Access Token URL
|
||||
description: URL used by authentik to retrive tokens.
|
||||
type: string
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
x-nullable: true
|
||||
profile_url:
|
||||
title: Profile URL
|
||||
description: URL used by authentik to get user information.
|
||||
type: string
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
x-nullable: true
|
||||
consumer_key:
|
||||
title: Consumer key
|
||||
type: string
|
||||
@ -17222,6 +17510,28 @@ definitions:
|
||||
\ log out manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
type: string
|
||||
minLength: 1
|
||||
StageUserSetting:
|
||||
required:
|
||||
- object_uid
|
||||
- component
|
||||
- title
|
||||
type: object
|
||||
properties:
|
||||
object_uid:
|
||||
title: Object uid
|
||||
type: string
|
||||
minLength: 1
|
||||
component:
|
||||
title: Component
|
||||
type: string
|
||||
minLength: 1
|
||||
title:
|
||||
title: Title
|
||||
type: string
|
||||
minLength: 1
|
||||
configure_flow:
|
||||
title: Configure flow
|
||||
type: boolean
|
||||
AuthenticatorStaticStage:
|
||||
required:
|
||||
- name
|
||||
|
1
web/authentik/sources/plex.svg
Normal file
1
web/authentik/sources/plex.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" ?><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title/><path d="M11.643 0H4.68l7.679 12L4.68 24h6.963l7.677-12-7.677-12"/></svg>
|
After Width: | Height: | Size: 175 B |
@ -81,7 +81,7 @@ http {
|
||||
location /static/ {
|
||||
expires 31d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
add_header X-authentik-version "2021.4.1";
|
||||
add_header X-authentik-version "2021.4.3";
|
||||
add_header Vary X-authentik-version;
|
||||
}
|
||||
|
||||
|
12
web/package-lock.json
generated
12
web/package-lock.json
generated
@ -1956,9 +1956,9 @@
|
||||
}
|
||||
},
|
||||
"@types/codemirror": {
|
||||
"version": "0.0.108",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
|
||||
"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
|
||||
"version": "0.0.109",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz",
|
||||
"integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==",
|
||||
"requires": {
|
||||
"@types/tern": "*"
|
||||
}
|
||||
@ -2647,9 +2647,9 @@
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
||||
},
|
||||
"chart.js": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.1.0.tgz",
|
||||
"integrity": "sha512-bKJi2VbC4fqZXlLbK7LKVvmG9crjoG9anfp96utZLyIGPuCx+YN+5/HDXy98QGt3lf74T8gKUPISUZL222tDJQ=="
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.1.1.tgz",
|
||||
"integrity": "sha512-ghNJersc9VD9MECwa5bL8gqvCkndW6RSCicdEHL9lIriNtXwKawlSmwo+u6KNXLYT2+f24GdFPBoynKW3ke4MQ=="
|
||||
},
|
||||
"chartjs-adapter-moment": {
|
||||
"version": "1.0.0",
|
||||
|
@ -53,14 +53,14 @@
|
||||
"@sentry/browser": "^6.2.5",
|
||||
"@sentry/tracing": "^6.2.5",
|
||||
"@types/chart.js": "^2.9.32",
|
||||
"@types/codemirror": "0.0.108",
|
||||
"@types/codemirror": "0.0.109",
|
||||
"@types/grecaptcha": "^3.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||
"@typescript-eslint/parser": "^4.22.0",
|
||||
"authentik-api": "file:api",
|
||||
"babel-plugin-macros": "^3.0.1",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^3.1.0",
|
||||
"chart.js": "^3.1.1",
|
||||
"chartjs-adapter-moment": "^1.0.0",
|
||||
"codemirror": "^5.60.0",
|
||||
"construct-style-sheets-polyfill": "^2.4.16",
|
||||
|
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
|
||||
export const ERROR_CLASS = "pf-m-danger";
|
||||
export const PROGRESS_CLASS = "pf-m-in-progress";
|
||||
export const CURRENT_CLASS = "pf-m-current";
|
||||
export const VERSION = "2021.4.1";
|
||||
export const VERSION = "2021.4.3";
|
||||
export const PAGE_SIZE = 20;
|
||||
export const EVENT_REFRESH = "ak-refresh";
|
||||
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
||||
|
@ -33,7 +33,12 @@ export class RouterOutlet extends LitElement {
|
||||
css`
|
||||
:host {
|
||||
height: 100vh;
|
||||
background-color: var(--ak-dark-background, var(--pf-c-page--BackgroundColor)) !important;
|
||||
background-color: var(--pf-global--BackgroundColor--light-300) !important;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:host {
|
||||
background-color: var(--ak-dark-background) !important;
|
||||
}
|
||||
}
|
||||
*:first-child {
|
||||
height: 100%;
|
||||
|
@ -162,11 +162,11 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
</div>
|
||||
<footer class="pf-c-login__main-footer">
|
||||
<ul class="pf-c-login__main-footer-links">
|
||||
<li class="pf-c-login__main-footer-links-item">
|
||||
<a class="pf-c-button pf-m-primary pf-m-block" href="/">
|
||||
${t`Return`}
|
||||
</a>
|
||||
</li>
|
||||
<li class="pf-c-login__main-footer-links-item">
|
||||
<a class="pf-c-button pf-m-primary pf-m-block" href="/">
|
||||
${t`Return`}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>`
|
||||
};
|
||||
|
@ -68,7 +68,7 @@ msgstr "API request failed"
|
||||
msgid "Access Key"
|
||||
msgstr "Access Key"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:72
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:73
|
||||
msgid "Access token URL"
|
||||
msgstr "Access token URL"
|
||||
|
||||
@ -79,13 +79,13 @@ msgstr "Access token URL"
|
||||
msgid "Action"
|
||||
msgstr "Action"
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:45
|
||||
#: src/pages/groups/MemberSelectModal.ts:46
|
||||
#: src/pages/users/UserListPage.ts:51
|
||||
#: src/pages/users/UserViewPage.ts:116
|
||||
msgid "Active"
|
||||
msgstr "Active"
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:82
|
||||
#: src/pages/groups/MemberSelectModal.ts:83
|
||||
msgid "Add"
|
||||
msgstr "Add"
|
||||
|
||||
@ -105,7 +105,7 @@ msgstr "Additional group DN, prepended to the Base DN."
|
||||
msgid "Additional user DN, prepended to the Base DN."
|
||||
msgstr "Additional user DN, prepended to the Base DN."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:128
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:131
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:128
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:117
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:134
|
||||
@ -125,7 +125,7 @@ msgstr "Affected model:"
|
||||
msgid "Alert"
|
||||
msgstr "Alert"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:149
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:152
|
||||
msgid "Algorithm used to sign the JWT Tokens."
|
||||
msgstr "Algorithm used to sign the JWT Tokens."
|
||||
|
||||
@ -168,12 +168,12 @@ msgstr "App"
|
||||
|
||||
#: src/elements/user/UserConsentList.ts:29
|
||||
#: src/pages/admin-overview/TopApplicationsTable.ts:42
|
||||
#: src/pages/applications/ApplicationListPage.ts:104
|
||||
#: src/pages/applications/ApplicationListPage.ts:105
|
||||
#: src/pages/providers/ProviderListPage.ts:53
|
||||
msgid "Application"
|
||||
msgstr "Application"
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:68
|
||||
#: src/pages/applications/ApplicationListPage.ts:69
|
||||
msgid "Application Icon"
|
||||
msgstr "Application Icon"
|
||||
|
||||
@ -220,19 +220,19 @@ msgstr "Are you sure you want to delete {0} {objName} ?"
|
||||
msgid "Are you sure you want to update {0} \"{1}\"?"
|
||||
msgstr "Are you sure you want to update {0} \"{1}\"?"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:202
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:208
|
||||
msgid "Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr "Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:191
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:197
|
||||
msgid "Assertion valid not before"
|
||||
msgstr "Assertion valid not before"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:195
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:201
|
||||
msgid "Assertion valid not before current time + this value (Format: hours=-1;minutes=-2;seconds=-3)."
|
||||
msgstr "Assertion valid not before current time + this value (Format: hours=-1;minutes=-2;seconds=-3)."
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:198
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:204
|
||||
msgid "Assertion valid not on or after"
|
||||
msgstr "Assertion valid not on or after"
|
||||
|
||||
@ -259,8 +259,8 @@ msgstr "Attempted to log in as {0}"
|
||||
msgid "Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded."
|
||||
msgstr "Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded."
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:134
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:51
|
||||
#: src/pages/groups/GroupForm.ts:135
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:52
|
||||
#: src/pages/users/UserForm.ts:77
|
||||
msgid "Attributes"
|
||||
msgstr "Attributes"
|
||||
@ -274,13 +274,13 @@ msgstr "Audience"
|
||||
msgid "Authentication"
|
||||
msgstr "Authentication"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:165
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:189
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:245
|
||||
msgid "Authentication flow"
|
||||
msgstr "Authentication flow"
|
||||
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts:63
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:29
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:33
|
||||
msgid "Authenticator"
|
||||
msgstr "Authenticator"
|
||||
|
||||
@ -292,7 +292,7 @@ msgstr "Authorization"
|
||||
msgid "Authorization Code"
|
||||
msgstr "Authorization Code"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:65
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:66
|
||||
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:95
|
||||
msgid "Authorization URL"
|
||||
msgstr "Authorization URL"
|
||||
@ -342,19 +342,19 @@ msgstr "Backup status"
|
||||
msgid "Base DN"
|
||||
msgstr "Base DN"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:195
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:204
|
||||
msgid "Based on the Hashed User ID"
|
||||
msgstr "Based on the Hashed User ID"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:201
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:210
|
||||
msgid "Based on the User's Email. This is recommended over the UPN method."
|
||||
msgstr "Based on the User's Email. This is recommended over the UPN method."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:204
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:213
|
||||
msgid "Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains."
|
||||
msgstr "Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:198
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:207
|
||||
msgid "Based on the username"
|
||||
msgstr "Based on the username"
|
||||
|
||||
@ -416,7 +416,7 @@ msgstr "Can be in the format of 'unix://' when connecting to a local docker daem
|
||||
#: src/elements/forms/ConfirmationForm.ts:75
|
||||
#: src/elements/forms/DeleteForm.ts:86
|
||||
#: src/elements/forms/ModalForm.ts:71
|
||||
#: src/pages/groups/MemberSelectModal.ts:89
|
||||
#: src/pages/groups/MemberSelectModal.ts:90
|
||||
#: src/pages/users/UserActiveForm.ts:73
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
@ -588,15 +588,15 @@ msgstr "Configuration"
|
||||
msgid "Configuration flow"
|
||||
msgstr "Configuration flow"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:103
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:106
|
||||
msgid "Configure WebAuthn"
|
||||
msgstr "Configure WebAuthn"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:187
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:193
|
||||
msgid "Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected."
|
||||
msgstr "Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:233
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:242
|
||||
msgid "Configure how the issuer field of the ID Token should be filled."
|
||||
msgstr "Configure how the issuer field of the ID Token should be filled."
|
||||
|
||||
@ -604,15 +604,15 @@ msgstr "Configure how the issuer field of the ID Token should be filled."
|
||||
msgid "Configure settings relevant to your user profile."
|
||||
msgstr "Configure settings relevant to your user profile."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:208
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:217
|
||||
msgid "Configure what data should be used as unique User Identifier. For most cases, the default should be fine."
|
||||
msgstr "Configure what data should be used as unique User Identifier. For most cases, the default should be fine."
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:47
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:43
|
||||
msgid "Connect"
|
||||
msgstr "Connect"
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:34
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:30
|
||||
msgid "Connected."
|
||||
msgstr "Connected."
|
||||
|
||||
@ -649,11 +649,11 @@ msgstr "Consider Objects matching this filter to be Groups."
|
||||
msgid "Consider Objects matching this filter to be Users."
|
||||
msgstr "Consider Objects matching this filter to be Users."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:124
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:126
|
||||
msgid "Consumer key"
|
||||
msgstr "Consumer key"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:130
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:132
|
||||
msgid "Consumer secret"
|
||||
msgstr "Consumer secret"
|
||||
|
||||
@ -695,8 +695,8 @@ msgid "Copy Key"
|
||||
msgstr "Copy Key"
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts:120
|
||||
#: src/pages/applications/ApplicationListPage.ts:120
|
||||
#: src/pages/applications/ApplicationListPage.ts:128
|
||||
#: src/pages/applications/ApplicationListPage.ts:121
|
||||
#: src/pages/applications/ApplicationListPage.ts:129
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:122
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:130
|
||||
#: src/pages/events/RuleListPage.ts:91
|
||||
@ -737,12 +737,12 @@ msgstr "Copy Key"
|
||||
#: src/pages/stages/prompt/PromptStageForm.ts:98
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:50
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:58
|
||||
#: src/pages/users/UserListPage.ts:144
|
||||
#: src/pages/users/UserListPage.ts:152
|
||||
#: src/pages/users/UserListPage.ts:151
|
||||
#: src/pages/users/UserListPage.ts:159
|
||||
msgid "Create"
|
||||
msgstr "Create"
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:123
|
||||
#: src/pages/applications/ApplicationListPage.ts:124
|
||||
#: src/pages/providers/RelatedApplicationButton.ts:30
|
||||
msgid "Create Application"
|
||||
msgstr "Create Application"
|
||||
@ -808,7 +808,7 @@ msgstr "Create Stage binding"
|
||||
msgid "Create Token"
|
||||
msgstr "Create Token"
|
||||
|
||||
#: src/pages/users/UserListPage.ts:147
|
||||
#: src/pages/users/UserListPage.ts:154
|
||||
msgid "Create User"
|
||||
msgstr "Create User"
|
||||
|
||||
@ -832,7 +832,7 @@ msgstr "Create {0}"
|
||||
msgid "Created by"
|
||||
msgstr "Created by"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:86
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:90
|
||||
msgid "Created {0}"
|
||||
msgstr "Created {0}"
|
||||
|
||||
@ -846,7 +846,7 @@ msgstr "Creation Date"
|
||||
msgid "Customisation"
|
||||
msgstr "Customisation"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:249
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:255
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:212
|
||||
msgid "DSA-SHA1"
|
||||
msgstr "DSA-SHA1"
|
||||
@ -868,7 +868,7 @@ msgid "Define how notifications are sent to users, like Email or Webhook."
|
||||
msgstr "Define how notifications are sent to users, like Email or Webhook."
|
||||
|
||||
#: src/elements/forms/DeleteForm.ts:79
|
||||
#: src/pages/applications/ApplicationListPage.ts:111
|
||||
#: src/pages/applications/ApplicationListPage.ts:112
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:86
|
||||
#: src/pages/events/RuleListPage.ts:82
|
||||
#: src/pages/events/TransportListPage.ts:86
|
||||
@ -884,7 +884,7 @@ msgstr "Define how notifications are sent to users, like Email or Webhook."
|
||||
#: src/pages/stages/invitation/InvitationListPage.ts:68
|
||||
#: src/pages/stages/prompt/PromptListPage.ts:87
|
||||
#: src/pages/tokens/TokenListPage.ts:68
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:36
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:40
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:125
|
||||
#: src/pages/users/UserListPage.ts:115
|
||||
msgid "Delete"
|
||||
@ -963,11 +963,11 @@ msgstr "Determines how long a session lasts. Default of 0 seconds means that the
|
||||
msgid "Device classes which can be used to authenticate."
|
||||
msgstr "Device classes which can be used to authenticate."
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:59
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:63
|
||||
msgid "Device name"
|
||||
msgstr "Device name"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:213
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:219
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:176
|
||||
msgid "Digest algorithm"
|
||||
msgstr "Digest algorithm"
|
||||
@ -981,11 +981,11 @@ msgstr "Digits"
|
||||
msgid "Disable"
|
||||
msgstr "Disable"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:51
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:55
|
||||
msgid "Disable Static Tokens"
|
||||
msgstr "Disable Static Tokens"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:36
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:40
|
||||
msgid "Disable Time-based OTP"
|
||||
msgstr "Disable Time-based OTP"
|
||||
|
||||
@ -993,7 +993,7 @@ msgstr "Disable Time-based OTP"
|
||||
msgid "Disabled"
|
||||
msgstr "Disabled"
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:41
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:37
|
||||
msgid "Disconnect"
|
||||
msgstr "Disconnect"
|
||||
|
||||
@ -1010,11 +1010,11 @@ msgstr "Download"
|
||||
msgid "Dummy stage used for testing. Shows a simple continue button and always passes."
|
||||
msgstr "Dummy stage used for testing. Shows a simple continue button and always passes."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:226
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:235
|
||||
msgid "Each provider has a different issuer, based on the application slug."
|
||||
msgstr "Each provider has a different issuer, based on the application slug."
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:94
|
||||
#: src/pages/applications/ApplicationListPage.ts:95
|
||||
#: src/pages/applications/ApplicationViewPage.ts:91
|
||||
#: src/pages/applications/ApplicationViewPage.ts:105
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:74
|
||||
@ -1096,18 +1096,18 @@ msgstr "Enable"
|
||||
msgid "Enable StartTLS"
|
||||
msgstr "Enable StartTLS"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:67
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:55
|
||||
msgid "Enable Static Tokens"
|
||||
msgstr "Enable Static Tokens"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:52
|
||||
msgid "Enable Time-based OTP"
|
||||
msgstr "Enable Time-based OTP"
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:70
|
||||
msgid "Enable TOTP"
|
||||
msgstr "Enable TOTP"
|
||||
|
||||
#: src/pages/policies/BoundPoliciesList.ts:37
|
||||
#: src/pages/policies/PolicyBindingForm.ts:198
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:69
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:113
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:115
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:69
|
||||
msgid "Enabled"
|
||||
msgstr "Enabled"
|
||||
@ -1116,7 +1116,7 @@ msgstr "Enabled"
|
||||
msgid "Enrollment"
|
||||
msgstr "Enrollment"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:186
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:210
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:266
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts:107
|
||||
msgid "Enrollment flow"
|
||||
@ -1209,7 +1209,7 @@ msgstr "Execution logging"
|
||||
#: src/elements/oauth/UserCodeList.ts:30
|
||||
#: src/elements/oauth/UserRefreshList.ts:30
|
||||
#: src/elements/user/UserConsentList.ts:30
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:45
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:46
|
||||
msgid "Expires"
|
||||
msgstr "Expires"
|
||||
|
||||
@ -1255,8 +1255,8 @@ msgid "Expression using Python."
|
||||
msgstr "Expression using Python."
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:31
|
||||
msgid "External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML."
|
||||
msgstr "External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML."
|
||||
msgid "External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access."
|
||||
msgstr "External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access."
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderViewPage.ts:90
|
||||
msgid "External Host"
|
||||
@ -1328,17 +1328,17 @@ msgstr "Flow"
|
||||
msgid "Flow Overview"
|
||||
msgstr "Flow Overview"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:161
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:185
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:220
|
||||
msgid "Flow settings"
|
||||
msgstr "Flow settings"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:183
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:207
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:263
|
||||
msgid "Flow to use when authenticating existing users."
|
||||
msgstr "Flow to use when authenticating existing users."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:204
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:228
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:284
|
||||
msgid "Flow to use when enrolling new users."
|
||||
msgstr "Flow to use when enrolling new users."
|
||||
@ -1451,7 +1451,7 @@ msgstr "Group {0}"
|
||||
msgid "Groups"
|
||||
msgstr "Groups"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:146
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:149
|
||||
msgid "HS256 (Symmetric Encryption)"
|
||||
msgstr "HS256 (Symmetric Encryption)"
|
||||
|
||||
@ -1476,10 +1476,10 @@ msgid "Hide managed mappings"
|
||||
msgstr "Hide managed mappings"
|
||||
|
||||
#: src/pages/events/RuleForm.ts:93
|
||||
#: src/pages/groups/GroupForm.ts:131
|
||||
#: src/pages/groups/GroupForm.ts:132
|
||||
#: src/pages/outposts/OutpostForm.ts:98
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:169
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:171
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:178
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:177
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:167
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:193
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:114
|
||||
@ -1531,7 +1531,7 @@ msgstr "If this flag is set, this Stage will jump to the next Stage when no Invi
|
||||
msgid "If your authentik Instance is using a self-signed certificate, set this value."
|
||||
msgstr "If your authentik Instance is using a self-signed certificate, set this value."
|
||||
|
||||
#: src/pages/users/UserListPage.ts:136
|
||||
#: src/pages/users/UserListPage.ts:143
|
||||
msgid "Impersonate"
|
||||
msgstr "Impersonate"
|
||||
|
||||
@ -1552,11 +1552,11 @@ msgstr "Import certificates of external providers or create certificates to sign
|
||||
msgid "In case you can't access any other method."
|
||||
msgstr "In case you can't access any other method."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:218
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:227
|
||||
msgid "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint."
|
||||
msgstr "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:215
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:224
|
||||
msgid "Include claims in id_token"
|
||||
msgstr "Include claims in id_token"
|
||||
|
||||
@ -1589,7 +1589,7 @@ msgstr "Invitations"
|
||||
msgid "Is active"
|
||||
msgstr "Is active"
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:60
|
||||
#: src/pages/groups/GroupForm.ts:62
|
||||
msgid "Is superuser"
|
||||
msgstr "Is superuser"
|
||||
|
||||
@ -1600,15 +1600,15 @@ msgstr "Is superuser"
|
||||
msgid "Issuer"
|
||||
msgstr "Issuer"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:221
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:230
|
||||
msgid "Issuer mode"
|
||||
msgstr "Issuer mode"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:138
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:141
|
||||
msgid "JWT Algorithm"
|
||||
msgstr "JWT Algorithm"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:187
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:196
|
||||
msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
|
||||
msgstr "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
|
||||
|
||||
@ -1633,7 +1633,7 @@ msgstr "Label"
|
||||
msgid "Label shown next to/above the prompt."
|
||||
msgstr "Label shown next to/above the prompt."
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:46
|
||||
#: src/pages/groups/MemberSelectModal.ts:47
|
||||
#: src/pages/users/UserListPage.ts:52
|
||||
#: src/pages/users/UserViewPage.ts:108
|
||||
msgid "Last login"
|
||||
@ -1680,6 +1680,7 @@ msgstr "Library"
|
||||
#: src/flows/stages/identification/IdentificationStage.ts:134
|
||||
#: src/flows/stages/password/PasswordStage.ts:31
|
||||
#: src/flows/stages/prompt/PromptStage.ts:126
|
||||
#: src/pages/applications/ApplicationViewPage.ts:43
|
||||
#: src/pages/applications/ApplicationViewPage.ts:54
|
||||
#: src/pages/user-settings/UserDetailsPage.ts:38
|
||||
#: src/utils.ts:40
|
||||
@ -1692,8 +1693,8 @@ msgstr "Loading"
|
||||
#: src/pages/events/RuleForm.ts:90
|
||||
#: src/pages/flows/StageBindingForm.ts:89
|
||||
#: src/pages/flows/StageBindingForm.ts:106
|
||||
#: src/pages/groups/GroupForm.ts:76
|
||||
#: src/pages/groups/GroupForm.ts:127
|
||||
#: src/pages/groups/GroupForm.ts:77
|
||||
#: src/pages/groups/GroupForm.ts:128
|
||||
#: src/pages/outposts/OutpostForm.ts:74
|
||||
#: src/pages/outposts/OutpostForm.ts:96
|
||||
#: src/pages/outposts/ServiceConnectionDockerForm.ts:87
|
||||
@ -1706,21 +1707,21 @@ msgstr "Loading"
|
||||
#: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:108
|
||||
#: src/pages/property-mappings/PropertyMappingTestForm.ts:59
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:74
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:166
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:185
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:175
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:194
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:92
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:143
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:71
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:133
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:149
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:169
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:185
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:175
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:191
|
||||
#: src/pages/providers/saml/SAMLProviderImportForm.ts:55
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:164
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:190
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:153
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:181
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:202
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:177
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:205
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:226
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:126
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:240
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:261
|
||||
@ -1796,7 +1797,7 @@ msgstr "Matches an event against a set of criteria. If any of the configured val
|
||||
msgid "Maximum age (in days)"
|
||||
msgstr "Maximum age (in days)"
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:80
|
||||
#: src/pages/groups/GroupForm.ts:81
|
||||
#: src/pages/groups/GroupListPage.ts:47
|
||||
msgid "Members"
|
||||
msgstr "Members"
|
||||
@ -1845,7 +1846,7 @@ msgid "Monitor"
|
||||
msgstr "Monitor"
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts:86
|
||||
#: src/pages/applications/ApplicationListPage.ts:57
|
||||
#: src/pages/applications/ApplicationListPage.ts:58
|
||||
#: src/pages/crypto/CertificateKeyPairForm.ts:45
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:51
|
||||
#: src/pages/events/EventInfo.ts:51
|
||||
@ -1856,9 +1857,9 @@ msgstr "Monitor"
|
||||
#: src/pages/flows/BoundStagesList.ts:39
|
||||
#: src/pages/flows/FlowForm.ts:81
|
||||
#: src/pages/flows/FlowListPage.ts:47
|
||||
#: src/pages/groups/GroupForm.ts:51
|
||||
#: src/pages/groups/GroupForm.ts:53
|
||||
#: src/pages/groups/GroupListPage.ts:45
|
||||
#: src/pages/groups/MemberSelectModal.ts:44
|
||||
#: src/pages/groups/MemberSelectModal.ts:45
|
||||
#: src/pages/outposts/OutpostForm.ts:47
|
||||
#: src/pages/outposts/OutpostListPage.ts:50
|
||||
#: src/pages/outposts/ServiceConnectionDockerForm.ts:53
|
||||
@ -1887,7 +1888,7 @@ msgstr "Monitor"
|
||||
#: src/pages/sources/SourcesListPage.ts:51
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:54
|
||||
#: src/pages/sources/ldap/LDAPSourceViewPage.ts:64
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:98
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:100
|
||||
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:63
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:54
|
||||
#: src/pages/sources/saml/SAMLSourceViewPage.ts:66
|
||||
@ -1924,7 +1925,7 @@ msgstr "Name of the form field, also used to store the value."
|
||||
msgid "NameID Policy"
|
||||
msgstr "NameID Policy"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:174
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:180
|
||||
msgid "NameID Property Mapping"
|
||||
msgstr "NameID Property Mapping"
|
||||
|
||||
@ -1939,7 +1940,7 @@ msgstr "New version available!"
|
||||
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:61
|
||||
#: src/pages/groups/GroupListPage.ts:58
|
||||
#: src/pages/groups/MemberSelectModal.ts:56
|
||||
#: src/pages/groups/MemberSelectModal.ts:57
|
||||
#: src/pages/outposts/ServiceConnectionListPage.ts:64
|
||||
#: src/pages/policies/BoundPoliciesList.ts:118
|
||||
#: src/pages/policies/PolicyTestForm.ts:38
|
||||
@ -1996,6 +1997,10 @@ msgstr "No policies are currently bound to this object."
|
||||
msgid "No policies cached. Users may experience slow response times."
|
||||
msgstr "No policies cached. Users may experience slow response times."
|
||||
|
||||
#: src/pages/users/UserListPage.ts:135
|
||||
msgid "No recovery flow is configured."
|
||||
msgstr "No recovery flow is configured."
|
||||
|
||||
#: src/pages/flows/BoundStagesList.ts:114
|
||||
msgid "No stages are currently bound to this flow."
|
||||
msgstr "No stages are currently bound to this flow."
|
||||
@ -2016,7 +2021,7 @@ msgstr "Not available"
|
||||
msgid "Not configured action"
|
||||
msgstr "Not configured action"
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:44
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:40
|
||||
msgid "Not connected."
|
||||
msgstr "Not connected."
|
||||
|
||||
@ -2110,7 +2115,7 @@ msgstr "Only fail the policy, don't invalidate user's password."
|
||||
msgid "Only send notification once, for example when sending a webhook into a chat channel."
|
||||
msgstr "Only send notification once, for example when sending a webhook into a chat channel."
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:99
|
||||
#: src/pages/applications/ApplicationListPage.ts:100
|
||||
msgid "Open application"
|
||||
msgstr "Open application"
|
||||
|
||||
@ -2130,7 +2135,7 @@ msgstr "Optional Private Key. If this is set, you can use this keypair for encry
|
||||
msgid "Optional URL if the IDP supports Single-Logout."
|
||||
msgstr "Optional URL if the IDP supports Single-Logout."
|
||||
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:55
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:56
|
||||
msgid "Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON."
|
||||
msgstr "Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON."
|
||||
|
||||
@ -2204,7 +2209,7 @@ msgstr "Overview"
|
||||
msgid "PEM-encoded Certificate data."
|
||||
msgstr "PEM-encoded Certificate data."
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:66
|
||||
#: src/pages/groups/GroupForm.ts:68
|
||||
#: src/pages/groups/GroupListPage.ts:46
|
||||
msgid "Parent"
|
||||
msgstr "Parent"
|
||||
@ -2334,7 +2339,7 @@ msgstr "Private key available?"
|
||||
msgid "Private key, acquired from https://www.google.com/recaptcha/intro/v3.html."
|
||||
msgstr "Private key, acquired from https://www.google.com/recaptcha/intro/v3.html."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:79
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:80
|
||||
msgid "Profile URL"
|
||||
msgstr "Profile URL"
|
||||
|
||||
@ -2376,7 +2381,7 @@ msgstr "Property mappings used to user creation."
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:81
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:99
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:78
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:120
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:122
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:76
|
||||
msgid "Protocol settings"
|
||||
msgstr "Protocol settings"
|
||||
@ -2388,18 +2393,17 @@ msgstr "Provide support for protocols like SAML and OAuth to assigned applicatio
|
||||
#: src/elements/oauth/UserCodeList.ts:29
|
||||
#: src/elements/oauth/UserRefreshList.ts:29
|
||||
#: src/pages/applications/ApplicationForm.ts:100
|
||||
#: src/pages/applications/ApplicationListPage.ts:59
|
||||
#: src/pages/applications/ApplicationListPage.ts:60
|
||||
#: src/pages/applications/ApplicationViewPage.ts:68
|
||||
#: src/pages/providers/ProviderListPage.ts:34
|
||||
msgid "Provider"
|
||||
msgstr "Provider"
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:60
|
||||
#: src/pages/applications/ApplicationListPage.ts:61
|
||||
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:71
|
||||
msgid "Provider Type"
|
||||
msgstr "Provider Type"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:136
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:138
|
||||
msgid "Provider type"
|
||||
msgstr "Provider type"
|
||||
|
||||
@ -2407,6 +2411,7 @@ msgstr "Provider type"
|
||||
#: src/pages/admin-overview/AdminOverviewPage.ts:46
|
||||
#: src/pages/outposts/OutpostForm.ts:82
|
||||
#: src/pages/outposts/OutpostListPage.ts:51
|
||||
#: src/pages/providers/ProviderListPage.ts:34
|
||||
msgid "Providers"
|
||||
msgstr "Providers"
|
||||
|
||||
@ -2430,30 +2435,30 @@ msgstr "Public key, acquired from https://www.google.com/recaptcha/intro/v3.html
|
||||
msgid "Publisher"
|
||||
msgstr "Publisher"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:143
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:146
|
||||
msgid "RS256 (Asymmetric Encryption)"
|
||||
msgstr "RS256 (Asymmetric Encryption)"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:172
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:181
|
||||
msgid "RSA Key"
|
||||
msgstr "RSA Key"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:237
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:243
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:200
|
||||
msgid "RSA-SHA1"
|
||||
msgstr "RSA-SHA1"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:240
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:246
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:203
|
||||
msgid "RSA-SHA256"
|
||||
msgstr "RSA-SHA256"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:243
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:249
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:206
|
||||
msgid "RSA-SHA384"
|
||||
msgstr "RSA-SHA384"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:246
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:252
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:209
|
||||
msgid "RSA-SHA512"
|
||||
msgstr "RSA-SHA512"
|
||||
@ -2478,11 +2483,14 @@ msgstr "Recovery keys"
|
||||
msgid "Redirect"
|
||||
msgstr "Redirect"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:119
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts:107
|
||||
msgid "Redirect URIs"
|
||||
msgstr "Redirect URIs"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:119
|
||||
msgid "Redirect URIs/Origins"
|
||||
msgstr "Redirect URIs/Origins"
|
||||
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:104
|
||||
msgid "Redirect binding"
|
||||
msgstr "Redirect binding"
|
||||
@ -2525,7 +2533,7 @@ msgstr "Request"
|
||||
msgid "Request has been denied."
|
||||
msgstr "Request has been denied."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:86
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:87
|
||||
msgid "Request token URL"
|
||||
msgstr "Request token URL"
|
||||
|
||||
@ -2538,7 +2546,7 @@ msgstr "Required"
|
||||
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
|
||||
msgstr "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
|
||||
|
||||
#: src/pages/users/UserListPage.ts:133
|
||||
#: src/pages/users/UserListPage.ts:140
|
||||
#: src/pages/users/UserViewPage.ts:165
|
||||
msgid "Reset Password"
|
||||
msgstr "Reset Password"
|
||||
@ -2578,22 +2586,22 @@ msgstr "Return to device picker"
|
||||
msgid "SAML Attribute Name"
|
||||
msgstr "SAML Attribute Name"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:218
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:224
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:181
|
||||
msgid "SHA1"
|
||||
msgstr "SHA1"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:221
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:227
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:184
|
||||
msgid "SHA256"
|
||||
msgstr "SHA256"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:224
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:230
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:187
|
||||
msgid "SHA384"
|
||||
msgstr "SHA384"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:227
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:233
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:190
|
||||
msgid "SHA512"
|
||||
msgstr "SHA512"
|
||||
@ -2624,7 +2632,7 @@ msgstr "SMTP Username"
|
||||
msgid "SSO URL"
|
||||
msgstr "SSO URL"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:229
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:238
|
||||
msgid "Same identifier is used for all providers"
|
||||
msgstr "Same identifier is used for all providers"
|
||||
|
||||
@ -2638,7 +2646,7 @@ msgstr "Scope which the client can specify to access these properties."
|
||||
|
||||
#: src/elements/oauth/UserCodeList.ts:31
|
||||
#: src/elements/oauth/UserRefreshList.ts:31
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:152
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:155
|
||||
msgid "Scopes"
|
||||
msgstr "Scopes"
|
||||
|
||||
@ -2669,11 +2677,11 @@ msgstr "Select all rows"
|
||||
msgid "Select an identification method."
|
||||
msgstr "Select an identification method."
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:67
|
||||
#: src/pages/groups/MemberSelectModal.ts:68
|
||||
msgid "Select users to add"
|
||||
msgstr "Select users to add"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:168
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:177
|
||||
msgid "Select which scopes can be used by the client. The client stil has to specify the scope to access the data."
|
||||
msgstr "Select which scopes can be used by the client. The client stil has to specify the scope to access the data."
|
||||
|
||||
@ -2734,11 +2742,11 @@ msgstr "Service connection"
|
||||
msgid "Session duration"
|
||||
msgstr "Session duration"
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:209
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:215
|
||||
msgid "Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr "Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:205
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:211
|
||||
msgid "Session valid not on or after"
|
||||
msgstr "Session valid not on or after"
|
||||
|
||||
@ -2750,7 +2758,7 @@ msgstr "Set HTTP-Basic Authentication"
|
||||
msgid "Set a custom HTTP-Basic Authentication header based on values from authentik."
|
||||
msgstr "Set a custom HTTP-Basic Authentication header based on values from authentik."
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:138
|
||||
#: src/pages/groups/GroupForm.ts:139
|
||||
#: src/pages/outposts/OutpostForm.ts:109
|
||||
#: src/pages/outposts/ServiceConnectionKubernetesForm.ts:73
|
||||
#: src/pages/policies/PolicyTestForm.ts:78
|
||||
@ -2779,7 +2787,7 @@ msgstr "Shown as the Title in Flow pages."
|
||||
msgid "Sign up."
|
||||
msgstr "Sign up."
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:232
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:238
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:195
|
||||
msgid "Signature algorithm"
|
||||
msgstr "Signature algorithm"
|
||||
@ -2801,10 +2809,10 @@ msgid "Skip path regex"
|
||||
msgstr "Skip path regex"
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts:93
|
||||
#: src/pages/applications/ApplicationListPage.ts:58
|
||||
#: src/pages/applications/ApplicationListPage.ts:59
|
||||
#: src/pages/flows/FlowForm.ts:94
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:60
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:104
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:106
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:60
|
||||
msgid "Slug"
|
||||
msgstr "Slug"
|
||||
@ -2818,7 +2826,7 @@ msgstr "Something went wrong! Please try again later."
|
||||
msgid "Source"
|
||||
msgstr "Source"
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:21
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:18
|
||||
msgid "Source {0}"
|
||||
msgstr "Source {0}"
|
||||
|
||||
@ -2897,10 +2905,13 @@ msgid "State"
|
||||
msgstr "State"
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:104
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:77
|
||||
msgid "Static Tokens"
|
||||
msgstr "Static Tokens"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:62
|
||||
msgid "Static tokens"
|
||||
msgstr "Static tokens"
|
||||
|
||||
#: src/pages/stages/prompt/PromptForm.ts:75
|
||||
msgid "Static: Static value, displayed as-is."
|
||||
msgstr "Static: Static value, displayed as-is."
|
||||
@ -2913,13 +2924,13 @@ msgstr "Statically deny the flow. To use this stage effectively, disable *Evalua
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:44
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:59
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:48
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:63
|
||||
msgid "Status: Disabled"
|
||||
msgstr "Status: Disabled"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:18
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:22
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:22
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:26
|
||||
msgid "Status: Enabled"
|
||||
msgstr "Status: Enabled"
|
||||
|
||||
@ -2931,7 +2942,7 @@ msgstr "Stop impersonation"
|
||||
msgid "Subject"
|
||||
msgstr "Subject"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:190
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:199
|
||||
msgid "Subject mode"
|
||||
msgstr "Subject mode"
|
||||
|
||||
@ -2972,11 +2983,11 @@ msgstr "Successfully created certificate-key pair."
|
||||
msgid "Successfully created flow."
|
||||
msgstr "Successfully created flow."
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:44
|
||||
#: src/pages/groups/GroupForm.ts:46
|
||||
msgid "Successfully created group."
|
||||
msgstr "Successfully created group."
|
||||
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:38
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:39
|
||||
msgid "Successfully created invitation."
|
||||
msgstr "Successfully created invitation."
|
||||
|
||||
@ -3020,7 +3031,7 @@ msgid "Successfully created service-connection."
|
||||
msgstr "Successfully created service-connection."
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:47
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:50
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:51
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:47
|
||||
msgid "Successfully created source."
|
||||
msgstr "Successfully created source."
|
||||
@ -3100,7 +3111,7 @@ msgstr "Successfully updated certificate-key pair."
|
||||
msgid "Successfully updated details."
|
||||
msgstr "Successfully updated details."
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:50
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:54
|
||||
msgid "Successfully updated device."
|
||||
msgstr "Successfully updated device."
|
||||
|
||||
@ -3108,11 +3119,11 @@ msgstr "Successfully updated device."
|
||||
msgid "Successfully updated flow."
|
||||
msgstr "Successfully updated flow."
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:41
|
||||
#: src/pages/groups/GroupForm.ts:43
|
||||
msgid "Successfully updated group."
|
||||
msgstr "Successfully updated group."
|
||||
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:35
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:36
|
||||
msgid "Successfully updated invitation."
|
||||
msgstr "Successfully updated invitation."
|
||||
|
||||
@ -3156,7 +3167,7 @@ msgid "Successfully updated service-connection."
|
||||
msgstr "Successfully updated service-connection."
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:44
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:47
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:48
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:44
|
||||
msgid "Successfully updated source."
|
||||
msgstr "Successfully updated source."
|
||||
@ -3339,7 +3350,7 @@ msgstr "Time in minutes the token sent is valid."
|
||||
msgid "Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr "Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:62
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:77
|
||||
msgid "Time-based One-Time Passwords"
|
||||
msgstr "Time-based One-Time Passwords"
|
||||
|
||||
@ -3371,7 +3382,7 @@ msgstr "Token count"
|
||||
msgid "Token expiry"
|
||||
msgstr "Token expiry"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:132
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:135
|
||||
msgid "Token validity"
|
||||
msgstr "Token validity"
|
||||
|
||||
@ -3418,7 +3429,7 @@ msgstr "UI settings"
|
||||
msgid "UID"
|
||||
msgstr "UID"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:61
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:62
|
||||
msgid "URL settings"
|
||||
msgstr "URL settings"
|
||||
|
||||
@ -3426,19 +3437,19 @@ msgstr "URL settings"
|
||||
msgid "URL that the initial Login request is sent to."
|
||||
msgstr "URL that the initial Login request is sent to."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:69
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:70
|
||||
msgid "URL the user is redirect to to consent the authorization."
|
||||
msgstr "URL the user is redirect to to consent the authorization."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:83
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:84
|
||||
msgid "URL used by authentik to get user information."
|
||||
msgstr "URL used by authentik to get user information."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:76
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:77
|
||||
msgid "URL used by authentik to retrieve tokens."
|
||||
msgstr "URL used by authentik to retrieve tokens."
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:89
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:90
|
||||
msgid "URL used to request the initial token. This URL is only required for OAuth 1."
|
||||
msgstr "URL used to request the initial token. This URL is only required for OAuth 1."
|
||||
|
||||
@ -3458,7 +3469,7 @@ msgstr "Unknown"
|
||||
msgid "Up-to-date!"
|
||||
msgstr "Up-to-date!"
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:86
|
||||
#: src/pages/applications/ApplicationListPage.ts:87
|
||||
#: src/pages/applications/ApplicationViewPage.ts:97
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:66
|
||||
#: src/pages/events/RuleListPage.ts:62
|
||||
@ -3486,9 +3497,9 @@ msgstr "Up-to-date!"
|
||||
#: src/pages/stages/StageListPage.ts:85
|
||||
#: src/pages/stages/prompt/PromptListPage.ts:67
|
||||
#: src/pages/user-settings/UserDetailsPage.ts:81
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:43
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:46
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:67
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:47
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:50
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:71
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:105
|
||||
#: src/pages/users/UserActiveForm.ts:66
|
||||
#: src/pages/users/UserListPage.ts:68
|
||||
@ -3496,7 +3507,7 @@ msgstr "Up-to-date!"
|
||||
msgid "Update"
|
||||
msgstr "Update"
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:89
|
||||
#: src/pages/applications/ApplicationListPage.ts:90
|
||||
#: src/pages/applications/ApplicationViewPage.ts:100
|
||||
msgid "Update Application"
|
||||
msgstr "Update Application"
|
||||
@ -3699,7 +3710,7 @@ msgstr "Username: Same as Text input, but checks for and prevents duplicate user
|
||||
msgid "Users"
|
||||
msgstr "Users"
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:63
|
||||
#: src/pages/groups/GroupForm.ts:65
|
||||
msgid "Users added to this group will be superusers."
|
||||
msgstr "Users added to this group will be superusers."
|
||||
|
||||
@ -3711,6 +3722,10 @@ msgstr "Using flow"
|
||||
msgid "Using source"
|
||||
msgstr "Using source"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:123
|
||||
msgid "Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows."
|
||||
msgstr "Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows."
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:115
|
||||
msgid "Validate SSL Certificates of upstream servers."
|
||||
msgstr "Validate SSL Certificates of upstream servers."
|
||||
@ -3784,7 +3799,7 @@ msgstr "Warning: Provider not assigned to any application."
|
||||
msgid "WebAuthn Authenticators"
|
||||
msgstr "WebAuthn Authenticators"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:74
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:78
|
||||
msgid "WebAuthn Devices"
|
||||
msgstr "WebAuthn Devices"
|
||||
|
||||
@ -3852,7 +3867,7 @@ msgstr "X509 Subject"
|
||||
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:61
|
||||
#: src/pages/groups/GroupListPage.ts:58
|
||||
#: src/pages/groups/MemberSelectModal.ts:56
|
||||
#: src/pages/groups/MemberSelectModal.ts:57
|
||||
#: src/pages/outposts/ServiceConnectionListPage.ts:64
|
||||
#: src/pages/policies/BoundPoliciesList.ts:118
|
||||
#: src/pages/policies/PolicyTestForm.ts:38
|
||||
|
@ -68,7 +68,7 @@ msgstr ""
|
||||
msgid "Access Key"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:72
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:73
|
||||
msgid "Access token URL"
|
||||
msgstr ""
|
||||
|
||||
@ -79,13 +79,13 @@ msgstr ""
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:45
|
||||
#: src/pages/groups/MemberSelectModal.ts:46
|
||||
#: src/pages/users/UserListPage.ts:51
|
||||
#: src/pages/users/UserViewPage.ts:116
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:82
|
||||
#: src/pages/groups/MemberSelectModal.ts:83
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
@ -105,7 +105,7 @@ msgstr ""
|
||||
msgid "Additional user DN, prepended to the Base DN."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:128
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:131
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:128
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:117
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:134
|
||||
@ -125,7 +125,7 @@ msgstr ""
|
||||
msgid "Alert"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:149
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:152
|
||||
msgid "Algorithm used to sign the JWT Tokens."
|
||||
msgstr ""
|
||||
|
||||
@ -168,12 +168,12 @@ msgstr ""
|
||||
|
||||
#: src/elements/user/UserConsentList.ts:29
|
||||
#: src/pages/admin-overview/TopApplicationsTable.ts:42
|
||||
#: src/pages/applications/ApplicationListPage.ts:104
|
||||
#: src/pages/applications/ApplicationListPage.ts:105
|
||||
#: src/pages/providers/ProviderListPage.ts:53
|
||||
msgid "Application"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:68
|
||||
#: src/pages/applications/ApplicationListPage.ts:69
|
||||
msgid "Application Icon"
|
||||
msgstr ""
|
||||
|
||||
@ -216,19 +216,19 @@ msgstr ""
|
||||
msgid "Are you sure you want to update {0} \"{1}\"?"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:202
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:208
|
||||
msgid "Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:191
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:197
|
||||
msgid "Assertion valid not before"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:195
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:201
|
||||
msgid "Assertion valid not before current time + this value (Format: hours=-1;minutes=-2;seconds=-3)."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:198
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:204
|
||||
msgid "Assertion valid not on or after"
|
||||
msgstr ""
|
||||
|
||||
@ -255,8 +255,8 @@ msgstr ""
|
||||
msgid "Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:134
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:51
|
||||
#: src/pages/groups/GroupForm.ts:135
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:52
|
||||
#: src/pages/users/UserForm.ts:77
|
||||
msgid "Attributes"
|
||||
msgstr ""
|
||||
@ -270,13 +270,13 @@ msgstr ""
|
||||
msgid "Authentication"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:165
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:189
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:245
|
||||
msgid "Authentication flow"
|
||||
msgstr ""
|
||||
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts:63
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:29
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:33
|
||||
msgid "Authenticator"
|
||||
msgstr ""
|
||||
|
||||
@ -288,7 +288,7 @@ msgstr ""
|
||||
msgid "Authorization Code"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:65
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:66
|
||||
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:95
|
||||
msgid "Authorization URL"
|
||||
msgstr ""
|
||||
@ -338,19 +338,19 @@ msgstr ""
|
||||
msgid "Base DN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:195
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:204
|
||||
msgid "Based on the Hashed User ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:201
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:210
|
||||
msgid "Based on the User's Email. This is recommended over the UPN method."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:204
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:213
|
||||
msgid "Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:198
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:207
|
||||
msgid "Based on the username"
|
||||
msgstr ""
|
||||
|
||||
@ -412,7 +412,7 @@ msgstr ""
|
||||
#: src/elements/forms/ConfirmationForm.ts:75
|
||||
#: src/elements/forms/DeleteForm.ts:86
|
||||
#: src/elements/forms/ModalForm.ts:71
|
||||
#: src/pages/groups/MemberSelectModal.ts:89
|
||||
#: src/pages/groups/MemberSelectModal.ts:90
|
||||
#: src/pages/users/UserActiveForm.ts:73
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@ -582,15 +582,15 @@ msgstr ""
|
||||
msgid "Configuration flow"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:103
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:106
|
||||
msgid "Configure WebAuthn"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:187
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:193
|
||||
msgid "Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:233
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:242
|
||||
msgid "Configure how the issuer field of the ID Token should be filled."
|
||||
msgstr ""
|
||||
|
||||
@ -598,15 +598,15 @@ msgstr ""
|
||||
msgid "Configure settings relevant to your user profile."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:208
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:217
|
||||
msgid "Configure what data should be used as unique User Identifier. For most cases, the default should be fine."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:47
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:43
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:34
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:30
|
||||
msgid "Connected."
|
||||
msgstr ""
|
||||
|
||||
@ -643,11 +643,11 @@ msgstr ""
|
||||
msgid "Consider Objects matching this filter to be Users."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:124
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:126
|
||||
msgid "Consumer key"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:130
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:132
|
||||
msgid "Consumer secret"
|
||||
msgstr ""
|
||||
|
||||
@ -689,8 +689,8 @@ msgid "Copy Key"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts:120
|
||||
#: src/pages/applications/ApplicationListPage.ts:120
|
||||
#: src/pages/applications/ApplicationListPage.ts:128
|
||||
#: src/pages/applications/ApplicationListPage.ts:121
|
||||
#: src/pages/applications/ApplicationListPage.ts:129
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:122
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:130
|
||||
#: src/pages/events/RuleListPage.ts:91
|
||||
@ -731,12 +731,12 @@ msgstr ""
|
||||
#: src/pages/stages/prompt/PromptStageForm.ts:98
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:50
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:58
|
||||
#: src/pages/users/UserListPage.ts:144
|
||||
#: src/pages/users/UserListPage.ts:152
|
||||
#: src/pages/users/UserListPage.ts:151
|
||||
#: src/pages/users/UserListPage.ts:159
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:123
|
||||
#: src/pages/applications/ApplicationListPage.ts:124
|
||||
#: src/pages/providers/RelatedApplicationButton.ts:30
|
||||
msgid "Create Application"
|
||||
msgstr ""
|
||||
@ -802,7 +802,7 @@ msgstr ""
|
||||
msgid "Create Token"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/users/UserListPage.ts:147
|
||||
#: src/pages/users/UserListPage.ts:154
|
||||
msgid "Create User"
|
||||
msgstr ""
|
||||
|
||||
@ -826,7 +826,7 @@ msgstr ""
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:86
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:90
|
||||
msgid "Created {0}"
|
||||
msgstr ""
|
||||
|
||||
@ -840,7 +840,7 @@ msgstr ""
|
||||
msgid "Customisation"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:249
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:255
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:212
|
||||
msgid "DSA-SHA1"
|
||||
msgstr ""
|
||||
@ -862,7 +862,7 @@ msgid "Define how notifications are sent to users, like Email or Webhook."
|
||||
msgstr ""
|
||||
|
||||
#: src/elements/forms/DeleteForm.ts:79
|
||||
#: src/pages/applications/ApplicationListPage.ts:111
|
||||
#: src/pages/applications/ApplicationListPage.ts:112
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:86
|
||||
#: src/pages/events/RuleListPage.ts:82
|
||||
#: src/pages/events/TransportListPage.ts:86
|
||||
@ -878,7 +878,7 @@ msgstr ""
|
||||
#: src/pages/stages/invitation/InvitationListPage.ts:68
|
||||
#: src/pages/stages/prompt/PromptListPage.ts:87
|
||||
#: src/pages/tokens/TokenListPage.ts:68
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:36
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:40
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:125
|
||||
#: src/pages/users/UserListPage.ts:115
|
||||
msgid "Delete"
|
||||
@ -955,11 +955,11 @@ msgstr ""
|
||||
msgid "Device classes which can be used to authenticate."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:59
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:63
|
||||
msgid "Device name"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:213
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:219
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:176
|
||||
msgid "Digest algorithm"
|
||||
msgstr ""
|
||||
@ -973,11 +973,11 @@ msgstr ""
|
||||
msgid "Disable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:51
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:55
|
||||
msgid "Disable Static Tokens"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:36
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:40
|
||||
msgid "Disable Time-based OTP"
|
||||
msgstr ""
|
||||
|
||||
@ -985,7 +985,7 @@ msgstr ""
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:41
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:37
|
||||
msgid "Disconnect"
|
||||
msgstr ""
|
||||
|
||||
@ -1002,11 +1002,11 @@ msgstr ""
|
||||
msgid "Dummy stage used for testing. Shows a simple continue button and always passes."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:226
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:235
|
||||
msgid "Each provider has a different issuer, based on the application slug."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:94
|
||||
#: src/pages/applications/ApplicationListPage.ts:95
|
||||
#: src/pages/applications/ApplicationViewPage.ts:91
|
||||
#: src/pages/applications/ApplicationViewPage.ts:105
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:74
|
||||
@ -1088,18 +1088,18 @@ msgstr ""
|
||||
msgid "Enable StartTLS"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:67
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:55
|
||||
msgid "Enable Static Tokens"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:52
|
||||
msgid "Enable Time-based OTP"
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:70
|
||||
msgid "Enable TOTP"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/BoundPoliciesList.ts:37
|
||||
#: src/pages/policies/PolicyBindingForm.ts:198
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:69
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:113
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:115
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:69
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
@ -1108,7 +1108,7 @@ msgstr ""
|
||||
msgid "Enrollment"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:186
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:210
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:266
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts:107
|
||||
msgid "Enrollment flow"
|
||||
@ -1201,7 +1201,7 @@ msgstr ""
|
||||
#: src/elements/oauth/UserCodeList.ts:30
|
||||
#: src/elements/oauth/UserRefreshList.ts:30
|
||||
#: src/elements/user/UserConsentList.ts:30
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:45
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:46
|
||||
msgid "Expires"
|
||||
msgstr ""
|
||||
|
||||
@ -1247,7 +1247,7 @@ msgid "Expression using Python."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:31
|
||||
msgid "External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML."
|
||||
msgid "External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderViewPage.ts:90
|
||||
@ -1320,17 +1320,17 @@ msgstr ""
|
||||
msgid "Flow Overview"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:161
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:185
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:220
|
||||
msgid "Flow settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:183
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:207
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:263
|
||||
msgid "Flow to use when authenticating existing users."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:204
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:228
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:284
|
||||
msgid "Flow to use when enrolling new users."
|
||||
msgstr ""
|
||||
@ -1443,7 +1443,7 @@ msgstr ""
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:146
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:149
|
||||
msgid "HS256 (Symmetric Encryption)"
|
||||
msgstr ""
|
||||
|
||||
@ -1468,10 +1468,10 @@ msgid "Hide managed mappings"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/events/RuleForm.ts:93
|
||||
#: src/pages/groups/GroupForm.ts:131
|
||||
#: src/pages/groups/GroupForm.ts:132
|
||||
#: src/pages/outposts/OutpostForm.ts:98
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:169
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:171
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:178
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:177
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:167
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:193
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:114
|
||||
@ -1523,7 +1523,7 @@ msgstr ""
|
||||
msgid "If your authentik Instance is using a self-signed certificate, set this value."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/users/UserListPage.ts:136
|
||||
#: src/pages/users/UserListPage.ts:143
|
||||
msgid "Impersonate"
|
||||
msgstr ""
|
||||
|
||||
@ -1544,11 +1544,11 @@ msgstr ""
|
||||
msgid "In case you can't access any other method."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:218
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:227
|
||||
msgid "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:215
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:224
|
||||
msgid "Include claims in id_token"
|
||||
msgstr ""
|
||||
|
||||
@ -1581,7 +1581,7 @@ msgstr ""
|
||||
msgid "Is active"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:60
|
||||
#: src/pages/groups/GroupForm.ts:62
|
||||
msgid "Is superuser"
|
||||
msgstr ""
|
||||
|
||||
@ -1592,15 +1592,15 @@ msgstr ""
|
||||
msgid "Issuer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:221
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:230
|
||||
msgid "Issuer mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:138
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:141
|
||||
msgid "JWT Algorithm"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:187
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:196
|
||||
msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
|
||||
msgstr ""
|
||||
|
||||
@ -1625,7 +1625,7 @@ msgstr ""
|
||||
msgid "Label shown next to/above the prompt."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:46
|
||||
#: src/pages/groups/MemberSelectModal.ts:47
|
||||
#: src/pages/users/UserListPage.ts:52
|
||||
#: src/pages/users/UserViewPage.ts:108
|
||||
msgid "Last login"
|
||||
@ -1672,6 +1672,7 @@ msgstr ""
|
||||
#: src/flows/stages/identification/IdentificationStage.ts:134
|
||||
#: src/flows/stages/password/PasswordStage.ts:31
|
||||
#: src/flows/stages/prompt/PromptStage.ts:126
|
||||
#: src/pages/applications/ApplicationViewPage.ts:43
|
||||
#: src/pages/applications/ApplicationViewPage.ts:54
|
||||
#: src/pages/user-settings/UserDetailsPage.ts:38
|
||||
#: src/utils.ts:40
|
||||
@ -1684,8 +1685,8 @@ msgstr ""
|
||||
#: src/pages/events/RuleForm.ts:90
|
||||
#: src/pages/flows/StageBindingForm.ts:89
|
||||
#: src/pages/flows/StageBindingForm.ts:106
|
||||
#: src/pages/groups/GroupForm.ts:76
|
||||
#: src/pages/groups/GroupForm.ts:127
|
||||
#: src/pages/groups/GroupForm.ts:77
|
||||
#: src/pages/groups/GroupForm.ts:128
|
||||
#: src/pages/outposts/OutpostForm.ts:74
|
||||
#: src/pages/outposts/OutpostForm.ts:96
|
||||
#: src/pages/outposts/ServiceConnectionDockerForm.ts:87
|
||||
@ -1698,21 +1699,21 @@ msgstr ""
|
||||
#: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:108
|
||||
#: src/pages/property-mappings/PropertyMappingTestForm.ts:59
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:74
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:166
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:185
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:175
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:194
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:92
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:143
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:71
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:133
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:149
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:169
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:185
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:175
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:191
|
||||
#: src/pages/providers/saml/SAMLProviderImportForm.ts:55
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:164
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:190
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:153
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:181
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:202
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:177
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:205
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:226
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:126
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:240
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:261
|
||||
@ -1788,7 +1789,7 @@ msgstr ""
|
||||
msgid "Maximum age (in days)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:80
|
||||
#: src/pages/groups/GroupForm.ts:81
|
||||
#: src/pages/groups/GroupListPage.ts:47
|
||||
msgid "Members"
|
||||
msgstr ""
|
||||
@ -1837,7 +1838,7 @@ msgid "Monitor"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts:86
|
||||
#: src/pages/applications/ApplicationListPage.ts:57
|
||||
#: src/pages/applications/ApplicationListPage.ts:58
|
||||
#: src/pages/crypto/CertificateKeyPairForm.ts:45
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:51
|
||||
#: src/pages/events/EventInfo.ts:51
|
||||
@ -1848,9 +1849,9 @@ msgstr ""
|
||||
#: src/pages/flows/BoundStagesList.ts:39
|
||||
#: src/pages/flows/FlowForm.ts:81
|
||||
#: src/pages/flows/FlowListPage.ts:47
|
||||
#: src/pages/groups/GroupForm.ts:51
|
||||
#: src/pages/groups/GroupForm.ts:53
|
||||
#: src/pages/groups/GroupListPage.ts:45
|
||||
#: src/pages/groups/MemberSelectModal.ts:44
|
||||
#: src/pages/groups/MemberSelectModal.ts:45
|
||||
#: src/pages/outposts/OutpostForm.ts:47
|
||||
#: src/pages/outposts/OutpostListPage.ts:50
|
||||
#: src/pages/outposts/ServiceConnectionDockerForm.ts:53
|
||||
@ -1879,7 +1880,7 @@ msgstr ""
|
||||
#: src/pages/sources/SourcesListPage.ts:51
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:54
|
||||
#: src/pages/sources/ldap/LDAPSourceViewPage.ts:64
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:98
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:100
|
||||
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:63
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:54
|
||||
#: src/pages/sources/saml/SAMLSourceViewPage.ts:66
|
||||
@ -1916,7 +1917,7 @@ msgstr ""
|
||||
msgid "NameID Policy"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:174
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:180
|
||||
msgid "NameID Property Mapping"
|
||||
msgstr ""
|
||||
|
||||
@ -1931,7 +1932,7 @@ msgstr ""
|
||||
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:61
|
||||
#: src/pages/groups/GroupListPage.ts:58
|
||||
#: src/pages/groups/MemberSelectModal.ts:56
|
||||
#: src/pages/groups/MemberSelectModal.ts:57
|
||||
#: src/pages/outposts/ServiceConnectionListPage.ts:64
|
||||
#: src/pages/policies/BoundPoliciesList.ts:118
|
||||
#: src/pages/policies/PolicyTestForm.ts:38
|
||||
@ -1988,6 +1989,10 @@ msgstr ""
|
||||
msgid "No policies cached. Users may experience slow response times."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/users/UserListPage.ts:135
|
||||
msgid "No recovery flow is configured."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/flows/BoundStagesList.ts:114
|
||||
msgid "No stages are currently bound to this flow."
|
||||
msgstr ""
|
||||
@ -2008,7 +2013,7 @@ msgstr ""
|
||||
msgid "Not configured action"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:44
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:40
|
||||
msgid "Not connected."
|
||||
msgstr ""
|
||||
|
||||
@ -2102,7 +2107,7 @@ msgstr ""
|
||||
msgid "Only send notification once, for example when sending a webhook into a chat channel."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:99
|
||||
#: src/pages/applications/ApplicationListPage.ts:100
|
||||
msgid "Open application"
|
||||
msgstr ""
|
||||
|
||||
@ -2122,7 +2127,7 @@ msgstr ""
|
||||
msgid "Optional URL if the IDP supports Single-Logout."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:55
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:56
|
||||
msgid "Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON."
|
||||
msgstr ""
|
||||
|
||||
@ -2196,7 +2201,7 @@ msgstr ""
|
||||
msgid "PEM-encoded Certificate data."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:66
|
||||
#: src/pages/groups/GroupForm.ts:68
|
||||
#: src/pages/groups/GroupListPage.ts:46
|
||||
msgid "Parent"
|
||||
msgstr ""
|
||||
@ -2326,7 +2331,7 @@ msgstr ""
|
||||
msgid "Private key, acquired from https://www.google.com/recaptcha/intro/v3.html."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:79
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:80
|
||||
msgid "Profile URL"
|
||||
msgstr ""
|
||||
|
||||
@ -2368,7 +2373,7 @@ msgstr ""
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:81
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:99
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:78
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:120
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:122
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:76
|
||||
msgid "Protocol settings"
|
||||
msgstr ""
|
||||
@ -2380,18 +2385,17 @@ msgstr ""
|
||||
#: src/elements/oauth/UserCodeList.ts:29
|
||||
#: src/elements/oauth/UserRefreshList.ts:29
|
||||
#: src/pages/applications/ApplicationForm.ts:100
|
||||
#: src/pages/applications/ApplicationListPage.ts:59
|
||||
#: src/pages/applications/ApplicationListPage.ts:60
|
||||
#: src/pages/applications/ApplicationViewPage.ts:68
|
||||
#: src/pages/providers/ProviderListPage.ts:34
|
||||
msgid "Provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:60
|
||||
#: src/pages/applications/ApplicationListPage.ts:61
|
||||
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:71
|
||||
msgid "Provider Type"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:136
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:138
|
||||
msgid "Provider type"
|
||||
msgstr ""
|
||||
|
||||
@ -2399,6 +2403,7 @@ msgstr ""
|
||||
#: src/pages/admin-overview/AdminOverviewPage.ts:46
|
||||
#: src/pages/outposts/OutpostForm.ts:82
|
||||
#: src/pages/outposts/OutpostListPage.ts:51
|
||||
#: src/pages/providers/ProviderListPage.ts:34
|
||||
msgid "Providers"
|
||||
msgstr ""
|
||||
|
||||
@ -2422,30 +2427,30 @@ msgstr ""
|
||||
msgid "Publisher"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:143
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:146
|
||||
msgid "RS256 (Asymmetric Encryption)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:172
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:181
|
||||
msgid "RSA Key"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:237
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:243
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:200
|
||||
msgid "RSA-SHA1"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:240
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:246
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:203
|
||||
msgid "RSA-SHA256"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:243
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:249
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:206
|
||||
msgid "RSA-SHA384"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:246
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:252
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:209
|
||||
msgid "RSA-SHA512"
|
||||
msgstr ""
|
||||
@ -2470,11 +2475,14 @@ msgstr ""
|
||||
msgid "Redirect"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:119
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts:107
|
||||
msgid "Redirect URIs"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:119
|
||||
msgid "Redirect URIs/Origins"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:104
|
||||
msgid "Redirect binding"
|
||||
msgstr ""
|
||||
@ -2517,7 +2525,7 @@ msgstr ""
|
||||
msgid "Request has been denied."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:86
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:87
|
||||
msgid "Request token URL"
|
||||
msgstr ""
|
||||
|
||||
@ -2530,7 +2538,7 @@ msgstr ""
|
||||
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/users/UserListPage.ts:133
|
||||
#: src/pages/users/UserListPage.ts:140
|
||||
#: src/pages/users/UserViewPage.ts:165
|
||||
msgid "Reset Password"
|
||||
msgstr ""
|
||||
@ -2570,22 +2578,22 @@ msgstr ""
|
||||
msgid "SAML Attribute Name"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:218
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:224
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:181
|
||||
msgid "SHA1"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:221
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:227
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:184
|
||||
msgid "SHA256"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:224
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:230
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:187
|
||||
msgid "SHA384"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:227
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:233
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:190
|
||||
msgid "SHA512"
|
||||
msgstr ""
|
||||
@ -2616,7 +2624,7 @@ msgstr ""
|
||||
msgid "SSO URL"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:229
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:238
|
||||
msgid "Same identifier is used for all providers"
|
||||
msgstr ""
|
||||
|
||||
@ -2630,7 +2638,7 @@ msgstr ""
|
||||
|
||||
#: src/elements/oauth/UserCodeList.ts:31
|
||||
#: src/elements/oauth/UserRefreshList.ts:31
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:152
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:155
|
||||
msgid "Scopes"
|
||||
msgstr ""
|
||||
|
||||
@ -2661,11 +2669,11 @@ msgstr ""
|
||||
msgid "Select an identification method."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/MemberSelectModal.ts:67
|
||||
#: src/pages/groups/MemberSelectModal.ts:68
|
||||
msgid "Select users to add"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:168
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:177
|
||||
msgid "Select which scopes can be used by the client. The client stil has to specify the scope to access the data."
|
||||
msgstr ""
|
||||
|
||||
@ -2726,11 +2734,11 @@ msgstr ""
|
||||
msgid "Session duration"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:209
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:215
|
||||
msgid "Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:205
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:211
|
||||
msgid "Session valid not on or after"
|
||||
msgstr ""
|
||||
|
||||
@ -2742,7 +2750,7 @@ msgstr ""
|
||||
msgid "Set a custom HTTP-Basic Authentication header based on values from authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:138
|
||||
#: src/pages/groups/GroupForm.ts:139
|
||||
#: src/pages/outposts/OutpostForm.ts:109
|
||||
#: src/pages/outposts/ServiceConnectionKubernetesForm.ts:73
|
||||
#: src/pages/policies/PolicyTestForm.ts:78
|
||||
@ -2771,7 +2779,7 @@ msgstr ""
|
||||
msgid "Sign up."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:232
|
||||
#: src/pages/providers/saml/SAMLProviderForm.ts:238
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:195
|
||||
msgid "Signature algorithm"
|
||||
msgstr ""
|
||||
@ -2793,10 +2801,10 @@ msgid "Skip path regex"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts:93
|
||||
#: src/pages/applications/ApplicationListPage.ts:58
|
||||
#: src/pages/applications/ApplicationListPage.ts:59
|
||||
#: src/pages/flows/FlowForm.ts:94
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:60
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:104
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:106
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:60
|
||||
msgid "Slug"
|
||||
msgstr ""
|
||||
@ -2810,7 +2818,7 @@ msgstr ""
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:21
|
||||
#: src/pages/user-settings/settings/SourceSettingsOAuth.ts:18
|
||||
msgid "Source {0}"
|
||||
msgstr ""
|
||||
|
||||
@ -2889,10 +2897,13 @@ msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:104
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:77
|
||||
msgid "Static Tokens"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:62
|
||||
msgid "Static tokens"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/stages/prompt/PromptForm.ts:75
|
||||
msgid "Static: Static value, displayed as-is."
|
||||
msgstr ""
|
||||
@ -2905,13 +2916,13 @@ msgstr ""
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:44
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:59
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:48
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:63
|
||||
msgid "Status: Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:18
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:22
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:22
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:26
|
||||
msgid "Status: Enabled"
|
||||
msgstr ""
|
||||
|
||||
@ -2923,7 +2934,7 @@ msgstr ""
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:190
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:199
|
||||
msgid "Subject mode"
|
||||
msgstr ""
|
||||
|
||||
@ -2964,11 +2975,11 @@ msgstr ""
|
||||
msgid "Successfully created flow."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:44
|
||||
#: src/pages/groups/GroupForm.ts:46
|
||||
msgid "Successfully created group."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:38
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:39
|
||||
msgid "Successfully created invitation."
|
||||
msgstr ""
|
||||
|
||||
@ -3012,7 +3023,7 @@ msgid "Successfully created service-connection."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:47
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:50
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:51
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:47
|
||||
msgid "Successfully created source."
|
||||
msgstr ""
|
||||
@ -3092,7 +3103,7 @@ msgstr ""
|
||||
msgid "Successfully updated details."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:50
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:54
|
||||
msgid "Successfully updated device."
|
||||
msgstr ""
|
||||
|
||||
@ -3100,11 +3111,11 @@ msgstr ""
|
||||
msgid "Successfully updated flow."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:41
|
||||
#: src/pages/groups/GroupForm.ts:43
|
||||
msgid "Successfully updated group."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:35
|
||||
#: src/pages/stages/invitation/InvitationForm.ts:36
|
||||
msgid "Successfully updated invitation."
|
||||
msgstr ""
|
||||
|
||||
@ -3148,7 +3159,7 @@ msgid "Successfully updated service-connection."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts:44
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:47
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:48
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts:44
|
||||
msgid "Successfully updated source."
|
||||
msgstr ""
|
||||
@ -3329,7 +3340,7 @@ msgstr ""
|
||||
msgid "Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts:62
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts:77
|
||||
msgid "Time-based One-Time Passwords"
|
||||
msgstr ""
|
||||
|
||||
@ -3361,7 +3372,7 @@ msgstr ""
|
||||
msgid "Token expiry"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:132
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:135
|
||||
msgid "Token validity"
|
||||
msgstr ""
|
||||
|
||||
@ -3408,7 +3419,7 @@ msgstr ""
|
||||
msgid "UID"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:61
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:62
|
||||
msgid "URL settings"
|
||||
msgstr ""
|
||||
|
||||
@ -3416,19 +3427,19 @@ msgstr ""
|
||||
msgid "URL that the initial Login request is sent to."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:69
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:70
|
||||
msgid "URL the user is redirect to to consent the authorization."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:83
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:84
|
||||
msgid "URL used by authentik to get user information."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:76
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:77
|
||||
msgid "URL used by authentik to retrieve tokens."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:89
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts:90
|
||||
msgid "URL used to request the initial token. This URL is only required for OAuth 1."
|
||||
msgstr ""
|
||||
|
||||
@ -3448,7 +3459,7 @@ msgstr ""
|
||||
msgid "Up-to-date!"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:86
|
||||
#: src/pages/applications/ApplicationListPage.ts:87
|
||||
#: src/pages/applications/ApplicationViewPage.ts:97
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:66
|
||||
#: src/pages/events/RuleListPage.ts:62
|
||||
@ -3476,9 +3487,9 @@ msgstr ""
|
||||
#: src/pages/stages/StageListPage.ts:85
|
||||
#: src/pages/stages/prompt/PromptListPage.ts:67
|
||||
#: src/pages/user-settings/UserDetailsPage.ts:81
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:43
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:46
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:67
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:47
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:50
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:71
|
||||
#: src/pages/user-settings/tokens/UserTokenList.ts:105
|
||||
#: src/pages/users/UserActiveForm.ts:66
|
||||
#: src/pages/users/UserListPage.ts:68
|
||||
@ -3486,7 +3497,7 @@ msgstr ""
|
||||
msgid "Update"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationListPage.ts:89
|
||||
#: src/pages/applications/ApplicationListPage.ts:90
|
||||
#: src/pages/applications/ApplicationViewPage.ts:100
|
||||
msgid "Update Application"
|
||||
msgstr ""
|
||||
@ -3689,7 +3700,7 @@ msgstr ""
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/groups/GroupForm.ts:63
|
||||
#: src/pages/groups/GroupForm.ts:65
|
||||
msgid "Users added to this group will be superusers."
|
||||
msgstr ""
|
||||
|
||||
@ -3701,6 +3712,10 @@ msgstr ""
|
||||
msgid "Using source"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:123
|
||||
msgid "Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts:115
|
||||
msgid "Validate SSL Certificates of upstream servers."
|
||||
msgstr ""
|
||||
@ -3774,7 +3789,7 @@ msgstr ""
|
||||
msgid "WebAuthn Authenticators"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:74
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts:78
|
||||
msgid "WebAuthn Devices"
|
||||
msgstr ""
|
||||
|
||||
@ -3840,7 +3855,7 @@ msgstr ""
|
||||
|
||||
#: src/pages/crypto/CertificateKeyPairListPage.ts:61
|
||||
#: src/pages/groups/GroupListPage.ts:58
|
||||
#: src/pages/groups/MemberSelectModal.ts:56
|
||||
#: src/pages/groups/MemberSelectModal.ts:57
|
||||
#: src/pages/outposts/ServiceConnectionListPage.ts:64
|
||||
#: src/pages/policies/BoundPoliciesList.ts:118
|
||||
#: src/pages/policies/PolicyTestForm.ts:38
|
||||
|
@ -22,7 +22,7 @@ export class ApplicationListPage extends TablePage<Application> {
|
||||
return t`Applications`;
|
||||
}
|
||||
pageDescription(): string {
|
||||
return t`External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML.`;
|
||||
return t`External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.`;
|
||||
}
|
||||
pageIcon(): string {
|
||||
return "pf-icon pf-icon-applications";
|
||||
@ -37,6 +37,7 @@ export class ApplicationListPage extends TablePage<Application> {
|
||||
page: page,
|
||||
pageSize: PAGE_SIZE,
|
||||
search: this.search || "",
|
||||
superuserFullList: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ export class ApplicationViewPage extends LitElement {
|
||||
render(): TemplateResult {
|
||||
return html`<ak-page-header
|
||||
icon=${this.application?.metaIcon || ""}
|
||||
header=${this.application?.name}
|
||||
header=${this.application?.name || t`Loading`}
|
||||
description=${ifDefined(this.application?.metaPublisher)}
|
||||
.iconImage=${true}>
|
||||
</ak-page-header>
|
||||
|
@ -29,12 +29,13 @@ export class GroupForm extends Form<Group> {
|
||||
}
|
||||
|
||||
send = (data: Group): Promise<Group> => {
|
||||
if (this.group) {
|
||||
if (this.group?.pk) {
|
||||
return new CoreApi(DEFAULT_CONFIG).coreGroupsUpdate({
|
||||
groupUuid: this.group.pk || "",
|
||||
data: data
|
||||
});
|
||||
} else {
|
||||
data.users = Array.from(this.group?.users || []) as unknown as Set<number>;
|
||||
return new CoreApi(DEFAULT_CONFIG).coreGroupsCreate({
|
||||
data: data
|
||||
});
|
||||
@ -60,7 +61,6 @@ export class GroupForm extends Form<Group> {
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Parent`}
|
||||
?required=${true}
|
||||
name="parent">
|
||||
<select class="pf-c-form-control">
|
||||
<option value="" ?selected=${this.group?.parent === undefined}>---------</option>
|
||||
@ -80,7 +80,7 @@ export class GroupForm extends Form<Group> {
|
||||
.confirm=${(items: User[]) => {
|
||||
// Because the model only has the IDs, map the user list to IDs
|
||||
const ids = items.map(u => u.pk || 0);
|
||||
if (!this.group) return Promise.reject();
|
||||
if (!this.group) this.group = {} as Group;
|
||||
this.group.users = new Set(Array.from(this.group?.users || []).concat(ids));
|
||||
this.requestUpdate();
|
||||
return Promise.resolve();
|
||||
@ -122,7 +122,7 @@ export class GroupForm extends Form<Group> {
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Attributes`}
|
||||
name="attributes">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(this.group?.attributes)}">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.group?.attributes, {}))}">
|
||||
</ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
@ -21,6 +21,8 @@ export class MemberSelectTable extends TableModal<User> {
|
||||
@property()
|
||||
confirm!: (selectedItems: User[]) => Promise<unknown>;
|
||||
|
||||
order = "username";
|
||||
|
||||
apiEndpoint(page: number): Promise<AKResponse<User>> {
|
||||
return new CoreApi(DEFAULT_CONFIG).coreUsersList({
|
||||
ordering: this.order,
|
||||
@ -40,10 +42,10 @@ export class MemberSelectTable extends TableModal<User> {
|
||||
|
||||
row(item: User): TemplateResult[] {
|
||||
return [
|
||||
html`<a href="#/identity/users/${item.pk}">
|
||||
html`<div>
|
||||
<div>${item.username}</div>
|
||||
<small>${item.name}</small>
|
||||
</a>`,
|
||||
</div>`,
|
||||
html`${item.isActive ? t`Yes` : t`No`}`,
|
||||
html`${first(item.lastLogin?.toLocaleString(), "-")}`,
|
||||
];
|
||||
|
@ -65,7 +65,7 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Kubeconfig`}
|
||||
name="kubeconfig">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(this.sc?.kubeconfig)}">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.sc?.kubeconfig, {}))}">
|
||||
</ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
@ -9,6 +9,7 @@ import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import "../../elements/forms/HorizontalFormElement";
|
||||
import "../../elements/CodeMirror";
|
||||
import { PolicyTest } from "authentik-api/src";
|
||||
import YAML from "yaml";
|
||||
|
||||
@customElement("ak-policy-test-form")
|
||||
export class PolicyTestForm extends Form<PolicyTest> {
|
||||
@ -75,7 +76,7 @@ export class PolicyTestForm extends Form<PolicyTest> {
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Context`}
|
||||
name="context">
|
||||
<ak-codemirror mode="yaml">
|
||||
<ak-codemirror mode="yaml" value=${YAML.stringify({})}>>
|
||||
</ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
@ -9,6 +9,7 @@ import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import "../../elements/forms/HorizontalFormElement";
|
||||
import "../../elements/CodeMirror";
|
||||
import { PolicyTest } from "authentik-api/src";
|
||||
import YAML from "yaml";
|
||||
|
||||
@customElement("ak-property-mapping-test-form")
|
||||
export class PolicyTestForm extends Form<PolicyTest> {
|
||||
@ -26,7 +27,8 @@ export class PolicyTestForm extends Form<PolicyTest> {
|
||||
send = (data: PolicyTest): Promise<PropertyMappingTestResult> => {
|
||||
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllTest({
|
||||
pmUuid: this.mapping?.pk || "",
|
||||
data: data
|
||||
data: data,
|
||||
formatResult: true,
|
||||
}).then(result => this.result = result);
|
||||
};
|
||||
|
||||
@ -64,7 +66,7 @@ export class PolicyTestForm extends Form<PolicyTest> {
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Context`}
|
||||
name="context">
|
||||
<ak-codemirror mode="yaml">
|
||||
<ak-codemirror mode="yaml" value=${YAML.stringify({})}>
|
||||
</ak-codemirror>
|
||||
</ak-form-element-horizontal>
|
||||
${this.result ? this.renderResult(): html``}
|
||||
|
@ -25,7 +25,7 @@ export class ProviderListPage extends TablePage<Provider> {
|
||||
return true;
|
||||
}
|
||||
pageTitle(): string {
|
||||
return t`Provider`;
|
||||
return t`Providers`;
|
||||
}
|
||||
pageDescription(): string {
|
||||
return t`Provide support for protocols like SAML and OAuth to assigned applications.`;
|
||||
|
@ -113,9 +113,12 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
|
||||
<input type="text" value="${first(this.provider?.clientSecret, randomString(128))}" class="pf-c-form-control">
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Redirect URIs`}
|
||||
label=${t`Redirect URIs/Origins`}
|
||||
name="redirectUris">
|
||||
<textarea class="pf-c-form-control">${this.provider?.redirectUris}</textarea>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>
|
||||
@ -154,9 +157,14 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
|
||||
ordering: "scope_name"
|
||||
}).then(scopes => {
|
||||
return scopes.results.map(scope => {
|
||||
const selected = Array.from(this.provider?.propertyMappings || []).some(su => {
|
||||
return su == scope.pk;
|
||||
});
|
||||
let selected = false;
|
||||
if (!this.provider?.propertyMappings) {
|
||||
selected = scope.managed?.startsWith("goauthentik.io/providers/oauth2/scope-") || false;
|
||||
} else {
|
||||
selected = Array.from(this.provider?.propertyMappings).some(su => {
|
||||
return su == scope.pk;
|
||||
});
|
||||
}
|
||||
return html`<option value=${ifDefined(scope.pk)} ?selected=${selected}>${scope.name}</option>`;
|
||||
});
|
||||
}), html`<option>${t`Loading...`}</option>`)}
|
||||
|
@ -154,9 +154,14 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
|
||||
ordering: "saml_name"
|
||||
}).then(mappings => {
|
||||
return mappings.results.map(mapping => {
|
||||
const selected = Array.from(this.provider?.propertyMappings || []).some(su => {
|
||||
return su == mapping.pk;
|
||||
});
|
||||
let selected = false;
|
||||
if (!this.provider?.propertyMappings) {
|
||||
selected = mapping.managed?.startsWith("goauthentik.io/providers/saml") || false;
|
||||
} else {
|
||||
selected = Array.from(this.provider?.propertyMappings).some(su => {
|
||||
return su == mapping.pk;
|
||||
});
|
||||
}
|
||||
return html`<option value=${ifDefined(mapping.pk)} ?selected=${selected}>${mapping.name}</option>`;
|
||||
});
|
||||
}), html`<option>${t`Loading...`}</option>`)}
|
||||
|
@ -128,6 +128,9 @@ export class SourceListPage extends TablePage<Source> {
|
||||
</span>
|
||||
<ak-proxy-form
|
||||
slot="form"
|
||||
.args=${{
|
||||
"modelName": type.modelName
|
||||
}}
|
||||
type=${type.component}>
|
||||
</ak-proxy-form>
|
||||
<button slot="trigger" class="pf-c-dropdown__menu-item">
|
||||
|
@ -22,12 +22,18 @@ export class OAuthSourceForm extends Form<OAuthSource> {
|
||||
});
|
||||
}
|
||||
|
||||
@property()
|
||||
modelName?: string;
|
||||
|
||||
@property({attribute: false})
|
||||
source?: OAuthSource;
|
||||
|
||||
@property({type: Boolean})
|
||||
showUrlOptions = false;
|
||||
|
||||
@property({type: Boolean})
|
||||
showRequestTokenURL = false;
|
||||
|
||||
getSuccessMessage(): string {
|
||||
if (this.source) {
|
||||
return t`Successfully updated source.`;
|
||||
@ -63,29 +69,30 @@ export class OAuthSourceForm extends Form<OAuthSource> {
|
||||
label=${t`Authorization URL`}
|
||||
?required=${true}
|
||||
name="authorizationUrl">
|
||||
<input type="text" value="${ifDefined(this.source?.authorizationUrl)}" class="pf-c-form-control" required>
|
||||
<input type="text" value="${first(this.source?.authorizationUrl, "")}" class="pf-c-form-control" required>
|
||||
<p class="pf-c-form__helper-text">${t`URL the user is redirect to to consent the authorization.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Access token URL`}
|
||||
?required=${true}
|
||||
name="accessTokenUrl">
|
||||
<input type="text" value="${ifDefined(this.source?.accessTokenUrl)}" class="pf-c-form-control" required>
|
||||
<input type="text" value="${first(this.source?.accessTokenUrl, "")}" class="pf-c-form-control" required>
|
||||
<p class="pf-c-form__helper-text">${t`URL used by authentik to retrieve tokens.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Profile URL`}
|
||||
?required=${true}
|
||||
name="profileUrl">
|
||||
<input type="text" value="${ifDefined(this.source?.profileUrl)}" class="pf-c-form-control" required>
|
||||
<input type="text" value="${first(this.source?.profileUrl, "")}" class="pf-c-form-control" required>
|
||||
<p class="pf-c-form__helper-text">${t`URL used by authentik to get user information.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
${this.showRequestTokenURL ? html`<ak-form-element-horizontal
|
||||
label=${t`Request token URL`}
|
||||
name="requestTokenUrl">
|
||||
<input type="text" value="${ifDefined(this.source?.requestTokenUrl)}" class="pf-c-form-control">
|
||||
<input type="text" value="${first(this.source?.requestTokenUrl, "")}" class="pf-c-form-control">
|
||||
<p class="pf-c-form__helper-text">${t`URL used to request the initial token. This URL is only required for OAuth 1.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
` : html``}
|
||||
</div>
|
||||
</ak-form-group>`;
|
||||
}
|
||||
@ -141,10 +148,31 @@ export class OAuthSourceForm extends Form<OAuthSource> {
|
||||
} else {
|
||||
this.showUrlOptions = false;
|
||||
}
|
||||
if ("data-request-token" in selected.attributes) {
|
||||
this.showRequestTokenURL = true;
|
||||
} else {
|
||||
this.showRequestTokenURL = false;
|
||||
}
|
||||
if (!this.source) {
|
||||
this.source = {} as OAuthSource;
|
||||
}
|
||||
this.source.providerType = selected.value;
|
||||
}}>
|
||||
${until(new SourcesApi(DEFAULT_CONFIG).sourcesOauthSourceTypes().then(types => {
|
||||
return types.map(type => {
|
||||
return html`<option ?data-urls-custom=${type.urlsCustomizable} value=${type.slug} ?selected=${this.source?.providerType === type.slug}>${type.name}</option>`;
|
||||
let selected = this.source?.providerType === type.slug;
|
||||
if (!this.source?.pk) {
|
||||
if (this.modelName?.replace("oauthsource", "") === type.slug) {
|
||||
selected = true;
|
||||
}
|
||||
}
|
||||
return html`<option
|
||||
?data-urls-custom=${type.urlsCustomizable}
|
||||
?data-request-token=${type.requestTokenUrl}
|
||||
value=${type.slug}
|
||||
?selected=${selected}>
|
||||
${type.name}
|
||||
</option>`;
|
||||
});
|
||||
}), html`<option>${t`Loading...`}</option>`)}
|
||||
</select>
|
||||
|
@ -7,6 +7,7 @@ import { Form } from "../../../elements/forms/Form";
|
||||
import "../../../elements/forms/HorizontalFormElement";
|
||||
import "../../../elements/CodeMirror";
|
||||
import YAML from "yaml";
|
||||
import { first } from "../../../utils";
|
||||
|
||||
@customElement("ak-invitation-form")
|
||||
export class InvitationForm extends Form<Invitation> {
|
||||
@ -46,7 +47,7 @@ export class InvitationForm extends Form<Invitation> {
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Attributes`}
|
||||
name="fixedData">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(this.invitation?.fixedData)}">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.invitation?.fixedData, {}))}">
|
||||
</ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">${t`Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
@ -56,7 +56,7 @@ export class UserSettingsPage extends LitElement {
|
||||
renderSourceSettings(source: UserSetting): TemplateResult {
|
||||
switch (source.component) {
|
||||
case "ak-user-settings-source-oauth":
|
||||
return html`<ak-user-settings-source-oauth objectId=${source.objectUid}>
|
||||
return html`<ak-user-settings-source-oauth objectId=${source.objectUid} title=${source.title}>
|
||||
</ak-user-settings-source-oauth>`;
|
||||
default:
|
||||
return html`<p>${t`Error: unsupported source settings: ${source.component}`}</p>`;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { customElement, html, TemplateResult } from "lit-element";
|
||||
import { customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { BaseUserSettings } from "./BaseUserSettings";
|
||||
import { OAuthSource, SourcesApi } from "authentik-api";
|
||||
import { SourcesApi } from "authentik-api";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
import { t } from "@lingui/macro";
|
||||
@ -9,22 +9,21 @@ import { AppURLManager } from "../../../api/legacy";
|
||||
@customElement("ak-user-settings-source-oauth")
|
||||
export class SourceSettingsOAuth extends BaseUserSettings {
|
||||
|
||||
@property()
|
||||
title!: string;
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`${until(new SourcesApi(DEFAULT_CONFIG).sourcesOauthRead({
|
||||
slug: this.objectId
|
||||
}).then((source) => {
|
||||
return html`<div class="pf-c-card">
|
||||
<div class="pf-c-card__title">
|
||||
${t`Source ${source.name}`}
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
${this.renderInner(source)}
|
||||
</div>
|
||||
</div>`;
|
||||
}))}`;
|
||||
return html`<div class="pf-c-card">
|
||||
<div class="pf-c-card__title">
|
||||
${t`Source ${this.title}`}
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
${this.renderInner()}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderInner(source: OAuthSource): TemplateResult {
|
||||
renderInner(): TemplateResult {
|
||||
return html`${until(new SourcesApi(DEFAULT_CONFIG).sourcesOauthUserConnectionsList({
|
||||
sourceSlug: this.objectId
|
||||
}).then((connection) => {
|
||||
@ -41,7 +40,7 @@ export class SourceSettingsOAuth extends BaseUserSettings {
|
||||
}
|
||||
return html`<p>${t`Not connected.`}</p>
|
||||
<a class="pf-c-button pf-m-primary"
|
||||
href=${AppURLManager.sourceOAuth(source.slug, "login")}>
|
||||
href=${AppURLManager.sourceOAuth(this.objectId, "login")}>
|
||||
${t`Connect`}
|
||||
</a>`;
|
||||
}))}`;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AuthenticatorsApi, StagesApi } from "authentik-api";
|
||||
import { AuthenticatorsApi } from "authentik-api";
|
||||
import { t } from "@lingui/macro";
|
||||
import { customElement, html, TemplateResult } from "lit-element";
|
||||
import { customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
@ -9,6 +9,9 @@ import { BaseUserSettings } from "./BaseUserSettings";
|
||||
@customElement("ak-user-settings-authenticator-static")
|
||||
export class UserSettingsAuthenticatorStatic extends BaseUserSettings {
|
||||
|
||||
@property({ type: Boolean })
|
||||
configureFlow = false;
|
||||
|
||||
renderEnabled(): TemplateResult {
|
||||
return html`<div class="pf-c-card__body">
|
||||
<p>
|
||||
@ -44,21 +47,17 @@ export class UserSettingsAuthenticatorStatic extends BaseUserSettings {
|
||||
</p>
|
||||
</div>
|
||||
<div class="pf-c-card__footer">
|
||||
${until(new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorTotpRead({ stageUuid: this.objectId}).then((stage) => {
|
||||
if (stage.configureFlow) {
|
||||
return html`<a href="${FlowURLManager.configure(stage.pk || "", "?next=/%23%2Fuser")}"
|
||||
class="pf-c-button pf-m-primary">${t`Enable Time-based OTP`}
|
||||
</a>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
${this.configureFlow ?
|
||||
html`<a href="${FlowURLManager.configure(this.objectId || "", "?next=/%23%2Fuser")}"
|
||||
class="pf-c-button pf-m-primary">${t`Enable Static Tokens`}
|
||||
</a>`: html``}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<div class="pf-c-card">
|
||||
<div class="pf-c-card__title">
|
||||
${t`Time-based One-Time Passwords`}
|
||||
${t`Static tokens`}
|
||||
</div>
|
||||
${until(new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsTotpList({}).then((devices) => {
|
||||
return devices.results.length > 0 ? this.renderEnabled() : this.renderDisabled();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AuthenticatorsApi, StagesApi } from "authentik-api";
|
||||
import { AuthenticatorsApi } from "authentik-api";
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, TemplateResult } from "lit-element";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
@ -10,6 +10,9 @@ import { BaseUserSettings } from "./BaseUserSettings";
|
||||
@customElement("ak-user-settings-authenticator-totp")
|
||||
export class UserSettingsAuthenticatorTOTP extends BaseUserSettings {
|
||||
|
||||
@property({ type: Boolean })
|
||||
configureFlow = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return super.styles.concat(STATIC_TOKEN_STYLE);
|
||||
}
|
||||
@ -59,21 +62,17 @@ export class UserSettingsAuthenticatorTOTP extends BaseUserSettings {
|
||||
</p>
|
||||
</div>
|
||||
<div class="pf-c-card__footer">
|
||||
${until(new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorStaticRead({ stageUuid: this.objectId}).then((stage) => {
|
||||
if (stage.configureFlow) {
|
||||
return html`<a href="${FlowURLManager.configure(stage.pk || "", "?next=/%23%2Fuser")}"
|
||||
class="pf-c-button pf-m-primary">${t`Enable Static Tokens`}
|
||||
</a>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
${this.configureFlow ?
|
||||
html`<a href="${FlowURLManager.configure(this.objectId || "", "?next=/%23%2Fuser")}"
|
||||
class="pf-c-button pf-m-primary">${t`Enable TOTP`}
|
||||
</a>`: html``}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<div class="pf-c-card">
|
||||
<div class="pf-c-card__title">
|
||||
${t`Static Tokens`}
|
||||
${t`Time-based One-Time Passwords`}
|
||||
</div>
|
||||
${until(new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsTotpList({}).then((devices) => {
|
||||
return devices.results.length > 0 ? this.renderEnabled() : this.renderDisabled();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CSSResult, customElement, html, TemplateResult } from "lit-element";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { t } from "@lingui/macro";
|
||||
import { AuthenticatorsApi, StagesApi, WebAuthnDevice } from "authentik-api";
|
||||
import { AuthenticatorsApi, WebAuthnDevice } from "authentik-api";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
@ -17,6 +17,9 @@ import { ifDefined } from "lit-html/directives/if-defined";
|
||||
@customElement("ak-user-settings-authenticator-webauthn")
|
||||
export class UserSettingsAuthenticatorWebAuthn extends BaseUserSettings {
|
||||
|
||||
@property({type: Boolean})
|
||||
configureFlow = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return super.styles.concat(PFDataList);
|
||||
}
|
||||
@ -96,14 +99,10 @@ export class UserSettingsAuthenticatorWebAuthn extends BaseUserSettings {
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pf-c-card__footer">
|
||||
${until(new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnRead({ stageUuid: this.objectId}).then((stage) => {
|
||||
if (stage.configureFlow) {
|
||||
return html`<a href="${FlowURLManager.configure(stage.pk || "", "?next=/%23%2Fuser")}"
|
||||
class="pf-c-button pf-m-primary">${t`Configure WebAuthn`}
|
||||
</a>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
${this.configureFlow ?
|
||||
html`<a href="${FlowURLManager.configure(this.objectId || "", "?next=/%23%2Fuser")}"
|
||||
class="pf-c-button pf-m-primary">${t`Configure WebAuthn`}
|
||||
</a>`: html``}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export class UserForm extends Form<User> {
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Attributes`}
|
||||
name="attributes">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(this.user?.attributes)}">
|
||||
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.user?.attributes, {}))}">
|
||||
</ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
@ -127,6 +127,13 @@ export class UserListPage extends TablePage<User> {
|
||||
message: t`Successfully generated recovery link`,
|
||||
description: rec.link
|
||||
});
|
||||
}).catch((ex: Response) => {
|
||||
ex.json().then(() => {
|
||||
showMessage({
|
||||
level: MessageLevel.error,
|
||||
message: t`No recovery flow is configured.`,
|
||||
});
|
||||
});
|
||||
});
|
||||
}}>
|
||||
${t`Reset Password`}
|
||||
|
@ -6,6 +6,6 @@ Starting with 2021.3.5, every authentik instance has a built-in API browser, whi
|
||||
|
||||
To generate an API client, you can use the Swagger schema at https://authentik.company/api/v2beta/swagger.json.
|
||||
|
||||
While testing, the API requests are authenticated by your browser session. To send an API request from outside the browser, you need to set an `Authorization` header.
|
||||
While testing, the API requests are authenticated by your browser session.
|
||||
|
||||
The value needs to be set to the base64-encoded token key.
|
||||
To send an API request from outside the browser, you need to set the `Authorization` Header to `Bearer <your token>`.
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
title: Setting up a local dev environment
|
||||
title: Getting started
|
||||
slug: /
|
||||
---
|
||||
|
||||
## Backend
|
||||
@ -27,6 +28,10 @@ Afterwards, you can start authentik by running `./manage.py runserver`. Generall
|
||||
|
||||
Most functions and classes have type-hints and docstrings, so it is recommended to install a Python Type-checking Extension in your IDE to navigate around the code.
|
||||
|
||||
Before committing code, run `make lint` to ensure your code is formatted well. This also requires `pyright`, which can be installed with npm.
|
||||
|
||||
Run `make gen` to run all unittests and generated an updated swagger document for any changes you made.
|
||||
|
||||
## Frontend
|
||||
|
||||
By default, no transpiled bundle of the frontend is included. To build the UI, you need Node 12 or newer.
|
||||
@ -54,3 +59,5 @@ npm run build
|
||||
```
|
||||
|
||||
If you want to make changes to the UI, run `npm run watch` instead.
|
||||
|
||||
To ensure the code is formatted well, run `npx eslint . --fix` and `npm run lit-analyse`.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user