OAuth 2.0 の概要
RFC 6749 - 「OAuth 2.0 認証フレームワーク」は、サードパーティ製アプリケーションを用いたサービスの認証に関するプロトコルを規定しています。 OAuth 2.0 では、トークンを使用して、サービスとユーザーから認証処理を抽象化しています。この方法では、サービス所有者がユーザーの認証情報を扱う必要がないため、より安全です。これは、RFC 5849OAuth 1.0 に代わるものです。
OAuth 2.0 フレームワークでは、クライアントタイプとして「パブリック」と「機密」の 2種類を定義しており、認証フローとして認証コードフロー、暗黙的コードグラント、その他いくつかのフローを規定しています。一般的な Qt アプリケーションは、パブリックなネイティブアプリケーションと見なされます。 パブリッククライアントアプリケーションとは、パスワードなどの機密情報を保持し、出荷時のバイナリに組み込むことが信頼できないアプリケーションのことです。
RFC 8252「ネイティブアプリ向け OAuth 2.0」では、ネイティブアプリケーション向けのベストプラクティスがさらに定義されています。具体的には、RFC 8252 ではブラウザを用いた認可フローが推奨されています。そのため、QtNetworkAuth クラスは、このフローの具体的な実装を提供しています。
Qt 6.9の新機能として、QtNetworkAuth はRFC 8628「OAuth 2.0 デバイス認証グラント」のサポートを提供します。このデバイスフローは、入力機能が限られている、あるいは実用的でないデバイスを対象としています。 このフローでは、認証グラントにおいて、対象デバイス自体の代わりにスマートフォンなどの二次デバイスを使用します。こうしたデバイスの例としては、テレビ、メディアコンソール、機械用HMI、IoTデバイスなどが挙げられます。ユーザーは、スマートフォンのアプリケーションを使用して、対象デバイスを認証することができます。
以下の表は、Qt Network Authorization がサポートする2つのOAuth 2.0フローを示しています:
| 側面 | 認証コードフロー | デバイス認証フロー |
|---|---|---|
| ネットワーク接続 | はい | はい |
| ユーザーの操作 | 同一デバイス上のブラウザ/ユーザーエージェント | 別のデバイス上のブラウザ/ユーザーエージェント |
| リダイレクト処理が必要 | はい | いいえ |
| デバイス上の入力機能 | 豊富な入力機能 | 入力機能が限定的、またはなし |
| 対象 | デスクトップおよびモバイルアプリ | テレビ、ゲーム機、HMI、IoTデバイス |
OAuth 2.0 では、通常はブラウザであるユーザーエージェントの使用が必須となります。詳細については、「Qt OAuth2 ブラウザサポート」を参照してください。
OAuth 2.0 クラス
Qt Network Authorization では、具体的な OAuth 2.0 クラスと抽象的な OAuth 2.0 クラスの両方が提供されています。抽象クラスはカスタムフローの実装を目的としており、具体的なクラスは具体的な実装を提供します。
C++クラスの一覧については、「QtNetworkAuth 」ページを参照してください。
Qt Network Authorization には、OAuth 2.0 フローを実装するための 2 つの抽象クラスがあります:
- OAuth 2.0 フローの実装クラスは主要なAPI を提供し、フローのオーケストレーターとしての役割を果たします。抽象クラスは `QAbstractOAuth2` であり、具体的な実装クラスとして `QOAuth2AuthorizationCodeFlow ` および `QOAuth2DeviceAuthorizationFlow` があります。
- リダイレクトや認証サーバーからの応答を処理するリプライハンドラクラス。リプライハンドラの抽象クラスは `QAbstractOAuthReplyHandler` であり、具体的な実装クラスは `QOAuthHttpServerReplyHandler ` および `QOAuthUriSchemeReplyHandler` です。リプライハンドラ間の主な違いは、処理するリダイレクトの種類にあります。QOAuth2AuthorizationCodeFlow はリダイレクトを処理するためにリプライハンドラを使用しますが、リダイレクトに基づかないQOAuth2DeviceAuthorizationFlow ではリプライハンドラは使用されません。
認証コードフロー
このセクションでは、ネイティブアプリケーション向けのRFC 6749 - 認証コードおよびRFC 8252 - ネイティブアプリからの認証リクエストに基づく認証コードフローの概要を説明します。
以下のサンプル構成を想定します:
QOAuth2AuthorizationCodeFlow m_oauth;
QOAuthUriSchemeReplyHandler m_handler;
m_oauth.setAuthorizationUrl(QUrl(authorizationUrl));
m_oauth.setTokenUrl(QUrl(accessTokenUrl));
m_oauth.setClientIdentifier(clientIdentifier);
m_oauth.setRequestedScopeTokens({scope});
connect(&m_oauth, &QAbstractOAuth::authorizeWithBrowser, this, &QDesktopServices::openUrl);
connect(&m_oauth, &QAbstractOAuth::granted, this, [this]() {
// Here we use QNetworkRequestFactory to store the access token
m_api.setBearerToken(m_oauth.token().toLatin1());
m_handler.close();
});
m_handler.setRedirectUrl(QUrl{"com.example.myqtapp://oauth2redirect"_L1});
m_oauth.setReplyHandler(&m_handler);
// Initiate the authorization
if (m_handler.listen()) {
m_oauth.grant();
}認証フローの段階
RFC 6749 に基づく認証コードフローには、主に 2 つの段階があります。それは、リソース認証(必要なユーザー認証を含む)と、それに続くアクセストークンの要求です。これらに続いて、オプションでアクセストークンの使用およびアクセストークンの更新が行われます。次の図は、これらの段階を示しています:

- 認証段階では、ユーザーの認証が行われ、ユーザーはリソースへのアクセスを許可します。これには、ユーザーによるブラウザ操作が必要です。
- 認証後、受け取った認証コードを使用してアクセストークン(およびオプションでリフレッシュトークン)を要求します。
- アクセストークンが取得されると、アプリケーションはそれを使用して対象のリソースにアクセスします。アクセストークンはリソースへのリクエストに含まれ、トークンの有効性を検証するのはリソースサーバーの役割です。ベアラートークンを使用する場合、リクエストの一部としてトークンを含める方法はいくつかあります。HTTPの
Authorizationヘッダーにトークンを含める方法が、おそらく最も一般的です。 - アクセストークンの更新。アクセストークンは通常、1時間後など、比較的短時間で失効します。アプリケーションがアクセストークンに加えてリフレッシュトークンを受け取った場合、そのリフレッシュトークンを使用して新しいアクセストークンをリクエストできます。アプリケーションは、有効期間の長いリフレッシュトークンを保持することで、新たな認証段階(ひいてはブラウザ操作の繰り返し)を回避することができます。
詳細とカスタマイズ
OAuth 2.0のフローは動的であり、仕様の実装は当初は難しい場合があります。下の図は、正常に完了した認証コードフローの主な詳細を示しています。

分かりやすくするため、図では一部のシグナルを省略していますが、全体として詳細と主なカスタマイズポイントを示しています。カスタマイズポイントとは、アプリケーションが使用できるさまざまなシグナルやスロット、およびQAbstractOAuth::setModifyParametersFunction() やQAbstractOAuth2::setNetworkRequestModifier() で設定可能なコールバックのことです。
返信ハンドラの選択
どのハンドラを使用するかは、redirect_uri要素によって決まります。redirect_uri は、認証段階の終了時にブラウザがリダイレクトされる先として設定されます。
ネイティブアプリケーションで認証応答を受信する場合、RFC 8252では、レスポンス URI スキームとして、private-use、loopback、https の 3 つの主要なタイプが規定されています。
- プライベートユース URI:OS がアプリケーションによるカスタム URI スキームの登録を許可している場合に使用できます。このようなカスタムスキームを持つ URL を開こうとすると、関連するネイティブアプリケーションが起動します。QOAuthUriSchemeReplyHandler を参照してください。
- HTTPS URI:OS がアプリケーションによるカスタム HTTPS URL の登録を許可している場合に使用できます。この URL を開こうとすると、関連するネイティブアプリケーションが起動します。OS がサポートしている場合は、このスキームの使用が推奨されます。QOAuthUriSchemeReplyHandler を参照してください。
- ループバックインターフェース: これらは、デスクトップアプリケーションや開発中のアプリケーションで一般的に使用されます。QOAuthHttpServerReplyHandler は、リダイレクトを処理するためのローカルサーバーを設定することで、これらのURIを処理するように設計されています。
選択は、次のようないくつかの要因によって異なります:
- 認証サーバーベンダーがサポートするリダイレクトURI。サポート状況はベンダーごとに異なり、多くの場合、特定のクライアントタイプやオペレーティングシステムに限定されます。また、アプリケーションが公開されているかどうかも、サポート状況に影響する場合があります。
- ターゲットプラットフォームでサポートされているリダイレクトURIスキーマ。
- アプリケーション固有の使いやすさ、セキュリティ、およびその他の要件。
RFC 8252では、他の方法に比べてセキュリティおよびユーザビリティの面で優れているため、https スキームの使用を推奨しています。
OAuth 2.0 デバイス認証グラント
RFC 8628 のOAuth 2.0 デバイス認証グラントは、入力機能に制限がある接続デバイス、またはユーザーエージェント(ブラウザ)の使用が現実的でない場合を想定しています。このフローを使用するデバイスの例としては、認証のために外部デバイスを必要とするスマート家電などが挙げられます。
以下のサンプル構成を考えてみましょう:
m_deviceFlow.setAuthorizationUrl(QUrl(authorizationUrl));
m_deviceFlow.setTokenUrl(QUrl(accessTokenUrl));
m_deviceFlow.setRequestedScopeTokens({scope});
m_deviceFlow.setClientIdentifier(clientIdentifier);
// クライアントシークレットが必要かどうかは、認証サーバーによって異なります
m_deviceFlow.setClientIdentifierSharedKey(clientSecret);
connect(&m_deviceFlow, &QOAuth2DeviceAuthorizationFlow::authorizeWithUserCode, this,
[](constQUrl&verificationUrl, constQString&userCode, constQUrl&completeVerificationUrl) {
if(completeVerificationUrl.isValid()) {
// 認証サーバーが 、必要なデータがURLパラメータの一部として
// すでに含まれている 完全なURLを提供している場合 、
// それを使用することも可能です
qDebug() << "Complete verification uri:" << completeVerificationUrl;
}else{
// 認証サーバーから提供されたのは検証用URLのみであるため、それを使用する
qDebug() << "Verification uri and usercode:" << verificationUrl << userCode;
}
}
);
connect(&m_deviceFlow, &QAbstractOAuth::granted, this, [this](){
// ここで QNetworkRequestFactory を使用してアクセストークンを保存します
m_api.setBearerToken(m_deviceFlow.token().toLatin1());
});
m_deviceFlow.grant();デバイスの認証グラントの各段階
デバイス認証グラントのフローには、認証の初期化、トークンのポーリング、認証の完了という3つの主要な段階があります。これらに続いて、オプションでトークンの使用やトークンの更新が行われます。次の図は、これらの段階を示しています:

- 認証は、認証サーバーへの HTTP リクエストの送信によって初期化されます。認証サーバーは、応答としてユーザーコード、検証用 URL、およびデバイスコードを提供します。
- 認証の初期化が完了すると、ユーザーには認証を完了するためのユーザーコードと検証用URLが提供されます。エンドユーザーに対する提供方法はさまざまで、画面上に表示されるURL、QRコード、電子メールなどがあります。詳細については、RFC 8628「ユーザーインタラクション」を参照してください。
- エンドユーザーによる認証の完了を待つ間、デバイスフローは認証サーバーに対してトークンの取得をポーリングします。前のステップで受け取ったデバイスコードは、認証セッションを照合するために使用されます。ポーリング間隔は認証サーバーによって決定され、通常は5秒です。
- エンドユーザーが承認または拒否を行うと、認証サーバーはポーリング要求に対して、要求されたトークンを返すか、拒否された場合はエラーコードを返します。これにより、認証は完了します。
詳細とカスタマイズ
次の図は、デバイス認証のグラントフローをより詳細に示しています。この図には、必要に応じてカスタマイズが必要な主な箇所が示されています。例えば、独自のパラメータや追加の認証情報などです。

リフレッシュトークン
トークンの更新には、認可サーバーが認可処理中にリフレッシュトークンを提供することが必要です。リフレッシュトークンの提供は認可サーバーの裁量に委ねられています。常に提供するサーバーもあれば、決して提供しないサーバーもあり、また、認可リクエストに特定のscope が含まれている場合にのみ提供するサーバーもあります。
次の図は、トークンの更新についてより詳細に示しています:

上の図に示すように、トークンのリフレッシュ時にも、通常のカスタマイズポイントが利用可能です。
アプリケーションの起動後にトークンを更新するには、アプリケーションがリフレッシュトークンを安全に永続化し、QAbstractOAuth2::setRefreshToken で設定する必要があります。その後、QAbstractOAuth2::refreshTokens を呼び出して新しいトークンを要求できます。
Qt 6.9の新機能として、アプリケーションはトークンを自動的に更新できるようになりました。詳細は、QAbstractOAuth2::accessTokenAboutToExpire 、QAbstractOAuth2::autoRefresh 、およびQAbstractOAuth2::refreshLeadTime を参照してください。
リフレッシュトークンの有効期限は、通常、認証サーバー側からは明示されません(サーバーのドキュメントに記載されている場合を除く)。その有効期間は、数日、数ヶ月、あるいはそれ以上になる場合があります。さらに、他のトークンと同様に、リフレッシュトークンはユーザーによって取り消される可能性があり、その結果、いつでも無効化される可能性があります。 したがって、QAbstractOAuth::requestFailed やQAbstractOAuth2::serverReportedErrorOccurred によるリフレッシュの試行が失敗したことを適切に検知することが重要です。
OAuth 2.0 のフローでは多くのユーザー操作が必要となり、ユーザー体験の妨げとなる可能性があります。こうした操作を最小限に抑えるため、トークンをユーザーに通知することなく自動的に更新することができます。詳細については、RFC 6749 - アクセストークンの更新を参照してください。
Qt の OpenID Connect サポート
OpenID Connect (OIDC)は、OAuth 2.0 を基盤としたシンプルなアイデンティティ層です。OIDC では、認証サーバーを利用してユーザーの身元を認証することができます。また、OIDC を使用することで、簡単なユーザープロファイル情報へのアクセスも可能です。
QtによるOIDCのサポートは、現時点ではIDトークンの取得に限定されています。IDトークンとは、認証イベントに関するクレームを含むJSON Web Token (JWT)のことです。
注:IDトークンの 検証や復号化は、現時点では実装されていません。JWTトークンの署名や検証には、サードパーティ製のJWTライブラリを使用する必要があります。
アプリケーションが受信したトークンの検証が可能である場合、そのトークンを使用してユーザーの身元を確実に確認することができます(OIDCプロバイダ自体が信頼されている限り)。
IDトークンは機密情報であるため、秘密として厳重に管理する必要があります。また、アクセストークンとは異なります。IDトークンはAPI呼び出しで送信することを意図したものではなく、その目的にはアクセストークンが使用されます。 一部のベンダーでは、アクセストークンに同じJWTフォーマットを使用する場合がありますが、同じフォーマットを使用する実際のIDトークンと混同しないよう注意してください。IDトークンでは、トークンを受け取ったクライアントがトークンの検証責任を負いますが、アクセストークンでは、トークンを受け入れるリソースサーバーが検証責任を負います。
IDトークンの取得
IDトークンの取得は、アクセストークンの取得と似ています。まず、適切なスコープを設定する必要があります。認証サーバーのベンダーによっては、profile やemail などの追加のスコープ指定子をサポートしている場合もありますが、すべてのOIDCリクエストにはopenid スコープを含める必要があります:
m_oauth.setRequestedScopeTokens({"openid"});OIDC では、nonce パラメータの使用を強く推奨します。これを行うには、適切なNonceMode が設定されていることを確認します。
// This is for illustrative purposes, 'Automatic' is the default mode
m_oauth.setNonceMode(QAbstractOAuth2::NonceMode::Automatic);最後のステップとして、QAbstractOAuth2::granted シグナル、あるいはQAbstractOAuth2::idTokenChanged を直接リッスンすることができます:
connect(&m_oauth, &QAbstractOAuth2::idTokenChanged, this, [this](const QString &token) {
Q_UNUSED(token); // Handle token
});IDトークンの検証
受信したIDトークンの検証は、認証フローにおいて極めて重要な部分であり、完全に実装しようとすると、やや複雑な作業となります。詳細については、「OpenID Connect ID Validation」をご覧ください。
簡単にまとめると、検証は以下の手順で構成されます:
- 必要に応じてトークンの復号化(JWEを参照)
- トークンのヘッダー、ペイロード、および署名を抽出する
- 署名の検証
- ペイロードのフィールド(
aud, iss, exp, nonce, iatなど)の検証
Qtは現在、IDトークンの検証をサポートしていませんが、jwt-cppなどのサードパーティ製JWTライブラリが利用可能です。
IDトークンの検証例
このセクションでは、簡単な検証例を説明します。前提条件として、開発環境にOpenSSLライブラリがインストールされており、アプリケーションプロジェクトのソースディレクトリ下の include フォルダにjwt-cpp が配置されている必要があります。
アプリケーションプロジェクトのCMakeLists.txt ファイルで、まず前提条件が満たされているかを確認します:
find_package(OpenSSL 1.0.0 QUIET)
set(JWT_CPP_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include")
if(OPENSSL_FOUND AND EXISTS "${JWT_CPP_INCLUDE_DIR}/jwt-cpp/jwt.h")次に、必要なインクルードとライブラリを追加します:
target_include_directories(networkauth_oauth_snippets PRIVATE "${JWT_CPP_INCLUDE_DIR}")
target_link_libraries(networkauth_oauth_snippets PRIVATE OpenSSL::SSL OpenSSL::Crypto)
target_compile_definitions(networkauth_oauth_snippets PRIVATE JWT_CPP_AVAILABLE)アプリケーションのソースファイルで、検証ライブラリをインクルードします:
#ifdef JWT_CPP_AVAILABLE
#include "jwt-cpp/jwt.h"
#endifアプリケーションがIDトークンを受信したら、その検証を行います。まず、JSON Web Key Sets(JWKS)から一致するキーを検索します(OpenID Connect Discoveryを参照)。
try {
const auto jwt = jwt::decode(m_oauth.idToken().toStdString());
const auto jwks = jwt::parse_jwks(m_jwks->toJson(QJsonDocument::Compact).toStdString());
const auto jwk = jwks.get_jwk(jwt.get_key_id());そして、実際の検証を行います:
// ここでは、モジュラスと指数を使用して鍵を導出します
const auton=jwk.get_jwk_claim("n").as_string();// モジュラス
const autoe=jwk.get_jwk_claim("e").as_string();// 指数
if(n.empty()||e.empty()) {
qWarning() << "Modulus or exponent empty";
return false;
}
if(jwt.get_algorithm()!= "RS256") {// この例では RS256 のみをサポートしています
qWarning() << "Unsupported algorithm:" << jwt.get_algorithm();
return false;
}
if(jwk.get_jwk_claim("kty").as_string()!= "RSA") {
qWarning() << "Unsupported key type:" << jwk.get_jwk_claim("kty").as_string();
return false;
}
if(jwk.has_jwk_claim("use")&&jwk.get_jwk_claim("use").as_string()!= "sig") {
qWarning() << "Key not for signature" << jwk.get_jwk_claim("use").as_string();
return false;
}
// シンプルで最小限の検証(特殊なケースや、例えば「sub」の検証は省略)。
// jwt-cpp は、「exp」、「iat」、「nbf」が存在する場合、これらもチェックします。
const autokeyPEM=jwt::helper::create_public_key_from_rsa_components(n,e);
autoverifier=jwt::verify()
.allow_algorithm(jwt::algorithm::rs256(keyPEM))
.with_claim("nonce",jwt::claim(m_oauth.nonce().toStdString()))
.with_issuer(m_oidcConfig->value("issuer"_L1).toString().toStdString())
.with_audience(std::string(clientIdentifier.data()))
.leeway(60UL);
verifier.verify(jwt);
qDebug() << "ID Token verified successfully";
return true;
}catch(conststd::exception&e) {
// エラーを処理する。あるいは、jwt-cpp の呼び出しにエラーパラメータを渡す
qWarning() << "ID Token verification failed" << e.what();
return false;
}IDトークンの値の読み取り
IDトークンはJSON Web Token(JWT)形式であり、ドット. で区切られたヘッダー、ペイロード、および署名の各部分で構成されています。
IDトークンの値を読み取る方法は簡単です。例として、次のような構造体があると仮定します:
struct IDToken {
QJsonObject header;
QJsonObject payload;
QByteArray signature;
};また、次のような関数があるとします:
std::optional<IDToken> parseIDToken(const QString &token) const;トークンは次のように抽出できます:
if (token.isEmpty())
return std::nullopt;
QList<QByteArray> parts = token.toLatin1().split('.');
if (parts.size() != 3)
return std::nullopt;
QJsonParseError parsing;
QJsonDocument header = QJsonDocument::fromJson(
QByteArray::fromBase64(parts.at(0), QByteArray::Base64UrlEncoding), &parsing);
if (parsing.error != QJsonParseError::NoError || !header.isObject())
return std::nullopt;
QJsonDocument payload = QJsonDocument::fromJson(
QByteArray::fromBase64(parts.at(1), QByteArray::Base64UrlEncoding), &parsing);
if (parsing.error != QJsonParseError::NoError || !payload.isObject())
return std::nullopt;
QByteArray signature = QByteArray::fromBase64(parts.at(2), QByteArray::Base64UrlEncoding);
return IDToken{header.object(), payload.object(), signature};場合によっては、トークンがJSON Web Encryption(JWE)として暗号化されており、その内部にJWTトークンが含まれていることがあります。その場合は、まずトークンを復号化する必要があります。
OpenID Connect ディスカバリー
OpenID Connect Discovery は、OpenID プロバイダーとやり取りを行うために必要なプロバイダーの詳細情報を取得する方法を定義しています。これには、authorization_endpoint やtoken_endpoint といった URL などの情報が含まれます。
これらのプロバイダー情報はアプリケーション内で静的に設定することも可能ですが、実行時に情報を取得することで、さまざまなプロバイダーとのやり取りにおいて、より高い柔軟性と堅牢性が得られる可能性があります。
ディスカバリードキュメントの取得は、単純なHTTP GETリクエストで行います。このドキュメントは通常、https://<domain name>/.well-known/openid_configuration にあります。
m_network->get(request, this, [this](QRestReply &reply) {
if (reply.isSuccess()) {
if (auto doc = reply.readJson(); doc && doc->isObject())
m_oidcConfig = doc->object(); // Store the configuration
}
});特に、トークンの検証に関しては、jwks_uriフィールドが、現在の(公開)セキュリティ認証情報にアクセスするためのリンクを提供します。 これを利用することで、アプリケーション内にそのような認証情報を直接ハードコードする必要がなくなります。これは鍵のローテーションにも役立ちます。ベンダーは使用される鍵を随時変更する可能性があるため、最新の鍵を確保することが重要です。
鍵の取得も同様に、単純なHTTP GETリクエストで行えます:
m_network->get(request, this, [this](QRestReply &reply) {
if (reply.isSuccess()) {
if (auto doc = reply.readJson(); doc && doc->isObject())
m_jwks = doc; // Use the keys later to verify tokens
}
});キーセットには通常、複数のキーが含まれています。正しいキーはJWTヘッダーに示されています(キーを正しく照合するよう注意が必要です。キーID(kid )フィールドを確認するだけでは不十分です)。
OpenID UserInfo エンドポイント
OIDCプロバイダーが対応している場合、ユーザー情報にアクセスする別の方法として、OpenID Connect UserInfoエンドポイントを使用することができます。userinfoのURLは、OpenID Connectディスカバリードキュメントのuserinfo_endpoint フィールドに記載されています。
UserInfoエンドポイントはIDトークンを使用せず、アクセストークンを使用してアクセスします。UserInfoへのアクセスは、アクセストークンを使用して他のリソースにアクセスする場合と同様です。
アクセストークンが受信され、例えば次のように設定されていると仮定します:
QNetworkRequestFactory userInfoApi(url);
userInfoApi.setBearerToken(m_oauth.token().toLatin1());この場合、UserInfo へのアクセスは HTTP GET リクエストとなります:
m_network->get(userInfoApi.createRequest(), this, [this](QRestReply&reply) {
if(reply.isSuccess()) {
if(autodoc=reply.readJson(); doc&& doc->isObject())
qDebug() << doc->object(); // Use the userinfo
}
});© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.