I have read all the stack overflow questions related to the issue. I got some idea about it but it could not help me to solve this issue.
I have used service account for authorization. Because I don't want to display the authorization screen for my users. So I have created service account and enabled domain-wide delegation authority in GoogleAPI console.
I need to create courses in the user's google classroom in a programmatical way. I have done using OAuth client ID and OAuth Client secret by following the java Quickstart. After completing the authorization token has been stored in the project directory. Using this token I can create courses in the authorized user's google classroom. Since I need to create courses in google classroom for many users in my domain. So I used service account. When I tried to implement it, I got the above error.
I have implemented it in the web application. For better understanding and code readability, I created a quickstart maven project and pasted the code. The code is working fine up to the System.out.println("Entering to list course method: "); line.
1) How to solve this issue?
2) Will it ask for authorization of Admin? Because in order to access the users data, we need access token. How can I get access token using service account?
public class ClassroomServiceAccount {
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String SERVICE_ACCOUNT_EMAIL = "xxxxxxx@projectName.iam.gserviceaccount.com";
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/MyProject.p12";
private static final List<String> SCOPES = Arrays.asList(ClassroomScopes.CLASSROOM_COURSES, ClassroomScopes.CLASSROOM_TOPICS, ClassroomScopes.CLASSROOM_ANNOUNCEMENTS);
public static void main(String... args) throws IOException, GeneralSecurityException {
HttpTransport httpTransport = new NetHttpTransport();
InputStream in = ClassroomServiceAccount.class.getResourceAsStream(SERVICE_ACCOUNT_PKCS12_FILE_PATH);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(in, "notasecret".toCharArray());
String alias = "key1";
Key key = keystore.getKey(alias, "notasecret".toCharArray());
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
System.out.println("This is public key : "+ publicKey);
// Return a key pair
KeyPair k = new KeyPair(publicKey, (PrivateKey) key);
System.out.println("This is k : "+ k.getPrivate());
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountPrivateKey(k.getPrivate())
.setServiceAccountScopes(SCOPES)
.setServiceAccountUser("email@yourdomain.com")
.build();
System.out.println("credentials : " + credential.getServiceAccountPrivateKey());
Classroom service = new Classroom.Builder(httpTransport, JSON_FACTORY, null)
.setApplicationName(APPLICATION_NAME)
.setHttpRequestInitializer(credential)
.build();
// Create courses in users google classroom
Course course = new Course();
course.setOwnerId("user@yourdomain.com");
course.setName("Science");
service.courses().create(course).execute();
}
}
I have solved this exception by changing the scopes. i.e., In my code, I have used the three scopes. Those three scopes should be matched with Gsuite's scope. While delegating domain-wide authority to the service account, we added scope. Both these scopes should be matched in order to avoid 401 unauthorized.