[iOS] WeatherKit REST API 인증 요청

날씨 데이터에 액세스할 개발자 토큰을 만듭니다

naljin
11 min readJun 15, 2022

들어가기 전에

제가..분명..성공하는거까지 잘 보고 잤거든여..? 다음날 부터 똑같은 코드가 안먹기 시작합니다..?

음.. 토큰 발급 전까지만 참고 하세요..?

Overview

WeatherKit REST API에 요청하려면 Apple Developer Program(ADP)의 자격을 부여받아야 합니다

모든 WeatherKit REST API 요청의 헤더에는 signed developer token 이 필요한데, 이는 ADP 멤버 및 요청 서비스를 식별하기 위함입니다.

하.. 시작해봅시다

private key 및 Service ID 생성

private key

developer token을 발급받기 위해서 먼저 WeatherKit identifier 및 private key 를 생성합니다

Apple 개발자 계정의 Certificates, Identifiers & Profiles 에서 WeatherKit 키를 생성하고, 다운로드하려면 Keys 메뉴를 선택합니다.

Service ID

그런 다음 Identifiers 메뉴에서 Service ID를 만듭니다.

web token 생성

WeatherKit은 JSON 웹 토큰(JWT) 규격을 지원하며 claims 라는 statements 과 메타데이터를 전달할 수 있습니다. JWT에 대한 자세한 내용은 JWT 규격을 참고하세요

JWT 에는 토큰에 담을 정보가 들어있음

여기에 담는 정보의 한 ‘조각’ 을 클레임(claim) 이라고 부르고, 이는 name / value 의 한 쌍으로 이뤄져있음

토큰에는 여러개의 클레임 들을 넣을 수 있음

출처 — [JWT] JSON Web Token 소개 및 구조

JWT 토큰을 만들고 서명하기 위해 온라인에서 사용할 수 있는 다양한 오픈 소스 라이브러리가 있습니다. 자세한 내용은 JWT.io 참고하세요

우리가 만들 JWT 의 pseudo code 형식은 아래와 같습니다

Y = Base64URLEncode(header) + '.' + Base64URLEncode(payload)
JWT token = Y + '.' + Base64URLEncode(ECDSASHA256(Y))

Header

다음 정보가 포함된 헤더를 사용해서 developer token 을 JSON object로 만듭니다

  • alg : 토큰에 서명할 알고리즘. 값을 ES256으로 설정
  • kid : 개발자 계정에서 얻은 10-character key identifier (아래 사진에서는 ABC123DEFG)
  • id :10-character Team ID (아래 사진에서는 DEF123GHIJ) 와 Service ID 로 구성된 identifier. 마침표로 구분함
{
"alg": "ES256",
"kid": "Key ID",
"id": "Team ID.com.sujinnaljin.weatherkit"
}

WeatherKit은 ES256 알고리즘으로 서명된 개발자 토큰만 지원하고, 안전하지 않은 개발자 토큰이나 다른 알고리즘으로 서명된 개발자 토큰은 거부합니다. 이러한 거부로 인해 401 오류 코드가 발생합니다

우선 헤더를 base64 로 인코딩하기 위해 터미널에서 아래 명령어를 입력합니다. 물론 안에 들어가는 값은 각자의 상황에 맞게 변경합니다.

echo -n '{ "alg": "ES256", "kid": "ABC123DEFG", "id": "DEF123GHIJ.com.sujinnaljin.weatherkit" }' | base64 | sed s/\+/-/ | sed -E s/=+$//
ewogICAgImFsZyI6ICJFUzI1NiIsCiAgICAia2lkIjogIkFCQzEyM0RFRkciLAogICAgImlkIjogIkRFRjEyM0dISUouY29tLnN1amlubmFqaW4ud2VhdGhlcmtpdCIKfQ==

아니면 그냥 아래 페이지에서 인코딩 합니다

Payload

토큰의 claims payload 에는 다음 정보들을 포함합니다. (아래 나열된 claims 만 포함되어 있는지 확인)

  • iss : issuer. 개발자 계정의 10-character Team ID. (ex. DEF123GHIJ )
  • iat : issued-at. 토큰이 생성된 시간. 값은 Epoch(세계 표준시) 이후 시간(초)
  • exp : expiration time. 토큰이 서버에서 승인되지 않는 시간. 값은 Epoch(세계 표준시) 이후 시간(초)
  • sub: subject public claim. 등록된 서비스 ID (ex. com.sujinnaljin.weatherkit)

Epoch time convert 는 아래 링크를 참고합니다

{
"iss": "Team ID",
"iat": 1655313073,
"exp": 1686849073,
"sub": "com.sujinnaljin.weatherkit"
}

헤더에서 한것과 마찬가지로 base64 인코딩을 진행합니다

ewogICAgImlzcyI6ICJERUYxMjNHSElKIiwKICAgICJpYXQiOiAxNjU1MzEzMDczLAogICAgImV4cCI6IDE2ODY4NDkwNzMsCiAgICAic3ViIjogImNvbS5zdWppbm5hamluLndlYXRoZXJraXQiCn0=

Signature

위에서 각각 인코딩한 헤더와 페이로드를 . 으로 연결하고 ES256 알고리즘을 사용하여 WeatherKit 개인 키로 서명합니다

ES256 알고리즘은 P-256 curve와 SHA-256 해시를 사용하는 ELDSA(Elliptic Curve Digital Signature Algorithm)의 JSON 웹 알고리즘(JWA) 이름입니다.

ES256서명(base64인코딩헤더.base64인코딩페이로드)

아래 터미널 명령어를 사용해서 ES256서명 후 base64로 인코딩 된 값을 뽑아낼 수 있습니다

echo -n "base64인코딩헤더.base64인코딩페이로드" | openssl dgst -sha256 -binary -sign AuthKey_ABC123DEFG.p8 | openssl enc -base64 | tr -d '\n=' | tr -- '+/' '-_'

이제 이 모든 값들을 . 으로 이어주면 우리의 jwt 토큰이 완성됩니다.

base64인코딩헤더.base64인코딩페이로드.base64인코딩signiture

만약 잘 안된다.. 못해먹겠다! 싶으면 아래 두 링크를 참고하고 .js 코드를 돌려보시길..

저도 새벽에 node 깔고 난리쳤었음요 ◠‿◠

서명된 JWT를 사용할 때마다 다음 지침을 준수합니다

  • 개인 키를 배포하지 않습니다. 앱이나 웹 사이트에 대한 토큰을 만들어야 하는 경우 인증된(authenticated) 서비스를 만들어 자신만의 토큰을 만들고 서명합니다.
  • 토큰 만료 시간에 유의합니다. 시간이 길수록 오버헤드가 적지만 시간이 짧으면 보안 수준이 높아집니다.
  • 토큰이 만료되기 전에 연장된 시간이 있는 경우 토큰을 안전하게 저장합니다.

Authorize 요청

developer token을 각 요청의 Authorization: Bearer header 의 매개 변수로 전달합니다

다음은 요청의 예입니다

curl -v -H 'Authorization: Bearer [developer token]' "https://weatherkit.apple.com/api/v1/availability/37.323/122.032?country=US"

아니면 이런식으로 쿼리 파라미터를 붙일 수도 있는데여

https://weatherkit.apple.com/api/v1/weather/en/51.677612/-2.937941?dataSets=currentWeather&timezone=Europe/London

요청 가능한 쿼리 파라미터에 대한 더 자세한 정보는 아래 문서를 확인하세여

참고

--

--