Lekcja 21: Nie ujawniaj danych logowania przy łączeniu z usługami
To query GraphQL pobiera dane logowania ze zmiennej środowiskowej i unika ich wydrukowania w odpowiedzi lub logach, zapobiegając tym samym zagrożeniom bezpieczeństwa:
query {
githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
@remove
_sendJSONObjectItemHTTPRequest(input:{
url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
method: PATCH,
options: {
auth: {
password: $__githubAccessToken
},
body: "{\"has_wiki\":false}"
}
})
}Poniżej znajduje się wyjaśnienie działania tego query.
Jak mogą wyciekać dane logowania
Często musimy podawać dane logowania przy łączeniu się z zewnętrznymi usługami. Na przykład REST API GitHuba wymaga tokenu dostępu dla endpointów, gdzie dane są prywatne lub są modyfikowane:
query {
_sendJSONObjectItemHTTPRequest(input:{
url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
method: PATCH,
options: {
auth: {
password: "{ GITHUB_ACCESS_TOKEN }"
},
body: "{\"has_wiki\":false}"
}
})
}Musimy zachować ostrożność i unikać ujawniania naszych danych logowania:
- W query GraphQL: Dane logowania nigdy nie mogą być osadzone w kodzie źródłowym, ponieważ byłyby w postaci zwykłego tekstu, co stanowiłoby zagrożenie bezpieczeństwa
- W odpowiedzi GraphQL: Jeśli pole łączące się z usługą zwróci błąd, do odpowiedzi GraphQL zostanie dodany komunikat o błędzie pod wpisem
errors; komunikat ten może zawierać nazwę pola, które się nie powiodło, wraz z jego argumentami, ujawniając tym samym dane logowania - W logach serwera: Jeśli dane logowania są dostępne przez zmienną, a ta zmienna jest przekazywana jako parametr URL, może zostać zapisana w logach serwera WWW
Query GraphQL zapobiegające wyciekaniu danych logowania
To query GraphQL przekazuje dane logowania do API GitHuba, unikając jednocześnie ich ujawnienia:
query {
githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
@remove
_sendJSONObjectItemHTTPRequest(input:{
url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
method: PATCH,
options: {
auth: {
password: $__githubAccessToken
},
body: "{\"has_wiki\":false}"
}
})
}Dzieje się tak dlatego, że:
- Dane logowania są pobierane ze zmiennej środowiskowej
GITHUB_ACCESS_TOKEN, więc nie muszą być osadzone w kodzie źródłowym - Pole
githubAccessTokenjest usuwane przez@remove, więc nie jest drukowane w odpowiedzi - Wejście
_sendJSONObjectItemHTTPRequest(auth:)odwołuje się do zmiennej dynamicznej$__githubAccessToken, więc jeśli pole zwróci błąd, w komunikacie o błędzie zostanie wydrukowany dosłowny ciąg"$__githubAccessToken"(nie jego wartość)
Aby zademonstrować ostatni punkt, podanie API GitHuba adresu URL nieistniejącego repozytorium "leoloso/NonExisting" powoduje błąd i otrzymujemy następującą odpowiedź (zwróć uwagę na auth: {password: $__githubAccessToken} w komunikacie o błędzie):
{
"errors": [
{
"message": "Client error: `PATCH https://api.github.com/repos/leoloso/NonExisting` resulted in a `404 Not Found` response:\n{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest/repos/repos#update-a-repository\"}\n",
"locations": [
{
"line": 21,
"column": 3
}
],
"extensions": {
"path": [
"_sendJSONObjectItemHTTPRequest(input: {url: \"https://api.github.com/repos/leoloso/NonExisting\", method: PATCH, options: {auth: {password: $__githubAccessToken}, body: \"{\"has_wiki\":false}\"}})",
"query { ... }"
],
"type": "QueryRoot",
"field": "_sendJSONObjectItemHTTPRequest(input: {url: \"https://api.github.com/repos/leoloso/NonExisting\", method: PATCH, options: {auth: {password: $__githubAccessToken}, body: \"{\"has_wiki\":false}\"}})",
"id": "root",
"code": "PoP/ComponentModel@e1"
}
}
],
"data": {
"_sendJSONObjectItemHTTPRequest": null
}
}