001/* 002 * Copyright (c) 2012, the Last.fm Java Project and Committers 003 * All rights reserved. 004 * 005 * Redistribution and use of this software in source and binary forms, with or without modification, are 006 * permitted provided that the following conditions are met: 007 * 008 * - Redistributions of source code must retain the above 009 * copyright notice, this list of conditions and the 010 * following disclaimer. 011 * 012 * - Redistributions in binary form must reproduce the above 013 * copyright notice, this list of conditions and the 014 * following disclaimer in the documentation and/or other 015 * materials provided with the distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 018 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 019 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 020 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 021 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 023 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 024 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 025 */ 026 027package de.umass.lastfm; 028 029import java.util.HashMap; 030import java.util.Map; 031import java.util.Map.Entry; 032import java.util.TreeMap; 033 034import de.umass.xml.DomElement; 035 036import static de.umass.util.StringUtilities.isMD5; 037import static de.umass.util.StringUtilities.map; 038import static de.umass.util.StringUtilities.md5; 039 040/** 041 * Provides bindings for the authentication methods of the last.fm API. 042 * See <a href="https://www.last.fm/api/authentication">https://www.last.fm/api/authentication</a> for 043 * authentication methods. 044 * 045 * @author Janni Kovacs 046 * @see Session 047 */ 048public class Authenticator { 049 050 private Authenticator() { 051 } 052 053 /** 054 * Create a web service session for a user. Used for authenticating a user when the password can be inputted by the user. 055 * 056 * @param username last.fm username 057 * @param password last.fm password in cleartext or 32-char md5 string 058 * @param apiKey The API key 059 * @param secret Your last.fm API secret 060 * @return a Session instance 061 * @see Session 062 */ 063 public static Session getMobileSession(String username, String password, String apiKey, String secret) { 064 if (!isMD5(password)) 065 password = md5(password); 066 String authToken = md5(username + password); 067 Map<String, String> params = map("api_key", apiKey, "username", username, "authToken", authToken); 068 String sig = createSignature("auth.getMobileSession", params, secret); 069 Result result = Caller.getInstance() 070 .call("auth.getMobileSession", apiKey, "username", username, "authToken", authToken, "api_sig", sig); 071 DomElement element = result.getContentElement(); 072 return Session.sessionFromElement(element, apiKey, secret); 073 } 074 075 /** 076 * Fetch an unathorized request token for an API account. 077 * 078 * @param apiKey A last.fm API key. 079 * @return a token 080 */ 081 public static String getToken(String apiKey) { 082 Result result = Caller.getInstance().call("auth.getToken", apiKey); 083 return result.getContentElement().getText(); 084 } 085 086 /** 087 * Fetch a session key for a user. 088 * 089 * @param token A token returned by {@link #getToken(String)} 090 * @param apiKey A last.fm API key 091 * @param secret Your last.fm API secret 092 * @return a Session instance 093 * @see Session 094 */ 095 public static Session getSession(String token, String apiKey, String secret) { 096 String m = "auth.getSession"; 097 Map<String, String> params = new HashMap<String, String>(); 098 params.put("api_key", apiKey); 099 params.put("token", token); 100 params.put("api_sig", createSignature(m, params, secret)); 101 Result result = Caller.getInstance().call(m, apiKey, params); 102 return Session.sessionFromElement(result.getContentElement(), apiKey, secret); 103 } 104 105 static String createSignature(String method, Map<String, String> params, String secret) { 106 params = new TreeMap<String, String>(params); 107 params.put("method", method); 108 StringBuilder b = new StringBuilder(100); 109 for (Entry<String, String> entry : params.entrySet()) { 110 b.append(entry.getKey()); 111 b.append(entry.getValue()); 112 } 113 b.append(secret); 114 return md5(b.toString()); 115 } 116}