View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  
23  package org.opencastproject.publication.youtube.auth;
24  
25  import com.google.api.client.auth.oauth2.Credential;
26  import com.google.api.client.auth.oauth2.StoredCredential;
27  import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
28  import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
29  import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
30  import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
31  import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
32  import com.google.api.client.http.javanet.NetHttpTransport;
33  import com.google.api.client.json.jackson2.JacksonFactory;
34  import com.google.api.client.util.store.DataStore;
35  import com.google.api.client.util.store.FileDataStoreFactory;
36  
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  import java.io.File;
41  import java.io.FileReader;
42  import java.io.IOException;
43  import java.text.MessageFormat;
44  
45  /**
46   * @see com.google.api.client.googleapis.auth.oauth2.GoogleCredential
47   */
48  public final class OAuth2CredentialFactoryImpl implements OAuth2CredentialFactory {
49  
50    private final Logger logger = LoggerFactory.getLogger(this.getClass());
51  
52    public OAuth2CredentialFactoryImpl() {
53    }
54  
55    @Override
56    public GoogleCredential getGoogleCredential(final ClientCredentials credentials) throws IOException {
57      // Use the default which is file-based; name and location are configurable
58      final DataStore<StoredCredential> datastore = getDataStore(credentials.getCredentialDatastore(),
59          credentials.getDataStoreDirectory());
60      return getGoogleCredential(datastore, credentials);
61    }
62  
63    @Override
64    public DataStore<StoredCredential> getDataStore(final String id, final String dataStoreDirectory)
65            throws IOException {
66      return new FileDataStoreFactory(new File(dataStoreDirectory)).getDataStore(id);
67    }
68  
69    @Override
70    public GoogleCredential getGoogleCredential(
71        final DataStore<StoredCredential> datastore,
72        final ClientCredentials authContext
73    ) throws IOException {
74      final GoogleCredential gCred;
75      final LocalServerReceiver localReceiver = new LocalServerReceiver();
76      final String accessToken;
77      final String refreshToken;
78  
79      try {
80        // Reads the client id and client secret from a file name passed in authContext
81        final GoogleClientSecrets gClientSecrets = GoogleClientSecrets.load(new JacksonFactory(),
82                new FileReader(authContext.getClientSecrets()));
83  
84        // Obtain tokens from credential in data store, or obtains a new one from
85        // Google if one doesn't exist
86        final StoredCredential sCred = datastore.get(authContext.getClientId());
87        if (sCred != null) {
88          accessToken = sCred.getAccessToken();
89          refreshToken = sCred.getRefreshToken();
90          logger.debug(MessageFormat.format(
91              "Found credential for client {0} in data store {1}", authContext.getClientId(), datastore.getId()));
92        } else {
93          // This flow supports installed applications
94          final GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
95                  new NetHttpTransport(), new JacksonFactory(), gClientSecrets, authContext.getScopes())
96              .setCredentialDataStore(datastore)
97              .setApprovalPrompt("auto")
98              .setAccessType("offline")
99              .build();
100         final Credential cred = new AuthorizationCodeInstalledApp(flow, localReceiver)
101             .authorize(authContext.getClientId());
102         accessToken = cred.getAccessToken();
103         refreshToken = cred.getRefreshToken();
104         logger.debug(MessageFormat.format(
105             "Created new credential for client {0} in data store {1}", authContext.getClientId(), datastore.getId()));
106       }
107       gCred = new GoogleCredential.Builder()
108           .setClientSecrets(gClientSecrets).setJsonFactory(new JacksonFactory())
109           .setTransport(new NetHttpTransport()).build();
110       gCred.setAccessToken(accessToken);
111       gCred.setRefreshToken(refreshToken);
112       logger.debug(MessageFormat.format(
113           "Found credential {0} using {1}", gCred.getRefreshToken(), authContext.toString()));
114     } finally {
115       localReceiver.stop();
116     }
117     return gCred;
118   }
119 }