1d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru/*
2d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Copyright (C) 2011 The Android Open Source Project
3d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *
4d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License");
5d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * you may not use this file except in compliance with the License.
6d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * You may obtain a copy of the License at
7d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *
8d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
9d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *
10d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
11d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
12d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * See the License for the specific language governing permissions and
14d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * limitations under the License.
15d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */
16d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
17d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Querupackage com.android.volley.toolbox;
18d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
19d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport com.android.volley.AuthFailureError;
20d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
21d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.accounts.Account;
22d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.accounts.AccountManager;
23d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.accounts.AccountManagerFuture;
24d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.content.Context;
25d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.content.Intent;
26d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.os.Bundle;
27d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
28d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru/**
29d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * An Authenticator that uses {@link AccountManager} to get auth
30d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * tokens of a specified type for a specified account.
31d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */
32d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Querupublic class AndroidAuthenticator implements Authenticator {
33d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private final Context mContext;
34d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private final Account mAccount;
35d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private final String mAuthTokenType;
362ff999381ba84f38218545430768949df7bbb001Evan Charlton    private final boolean mNotifyAuthFailure;
37d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
38d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    /**
39d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * Creates a new authenticator.
40d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * @param context Context for accessing AccountManager
41d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * @param account Account to authenticate as
42d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * @param authTokenType Auth token type passed to AccountManager
43d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     */
44d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public AndroidAuthenticator(Context context, Account account, String authTokenType) {
452ff999381ba84f38218545430768949df7bbb001Evan Charlton        this(context, account, authTokenType, false);
462ff999381ba84f38218545430768949df7bbb001Evan Charlton    }
472ff999381ba84f38218545430768949df7bbb001Evan Charlton
482ff999381ba84f38218545430768949df7bbb001Evan Charlton    /**
492ff999381ba84f38218545430768949df7bbb001Evan Charlton     * Creates a new authenticator.
502ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param context Context for accessing AccountManager
512ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param account Account to authenticate as
522ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param authTokenType Auth token type passed to AccountManager
532ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param notifyAuthFailure Whether to raise a notification upon auth failure
542ff999381ba84f38218545430768949df7bbb001Evan Charlton     */
552ff999381ba84f38218545430768949df7bbb001Evan Charlton    public AndroidAuthenticator(Context context, Account account, String authTokenType,
562ff999381ba84f38218545430768949df7bbb001Evan Charlton            boolean notifyAuthFailure) {
57d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        mContext = context;
58d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        mAccount = account;
59d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        mAuthTokenType = authTokenType;
602ff999381ba84f38218545430768949df7bbb001Evan Charlton        mNotifyAuthFailure = notifyAuthFailure;
61d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
62d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
63d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    /**
64d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * Returns the Account being used by this authenticator.
65d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     */
66d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public Account getAccount() {
67d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        return mAccount;
68d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
69d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
70d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    @Override
71d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public String getAuthToken() throws AuthFailureError {
72d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        final AccountManager accountManager = AccountManager.get(mContext);
73d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        AccountManagerFuture<Bundle> future = accountManager.getAuthToken(mAccount,
742ff999381ba84f38218545430768949df7bbb001Evan Charlton                mAuthTokenType, mNotifyAuthFailure, null, null);
75d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Bundle result;
76d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        try {
77d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            result = future.getResult();
78d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        } catch (Exception e) {
79d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            throw new AuthFailureError("Error while retrieving auth token", e);
80d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        }
81d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        String authToken = null;
82d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        if (future.isDone() && !future.isCancelled()) {
83d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            if (result.containsKey(AccountManager.KEY_INTENT)) {
84d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru                Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
85d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru                throw new AuthFailureError(intent);
86d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            }
87d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
88d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        }
89d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        if (authToken == null) {
90d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            throw new AuthFailureError("Got null auth token for type: " + mAuthTokenType);
91d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        }
92d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
93d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        return authToken;
94d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
95d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
96d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    @Override
97d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void invalidateAuthToken(String authToken) {
98d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        AccountManager.get(mContext).invalidateAuthToken(mAccount.type, authToken);
99d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
100d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru}
101