Keycloak Userstorage SPI: I add my JSON to the ID token and it still not shown when I request it? - keycloak

In my application I create the getAttributes() like this:
#Override
public Map<String, List<String>> getAttributes() {
String json = "";
ObjectMapper mapper = new ObjectMapper();
try {
User user = new User(user_params);
json = mapper.writeValueAsString(user);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
attributes.add("user", json);
return attributes;
}
Then on keycloak admin page:
create client named my-client
create client scope named my-scope
add on my-client --> Client Scopes page the my-scope to the Optional Client Scopes
go Client Scopes --> open my-scope --> Mappers --> create this mapper:
Yet when I request the tokens like this:
My ID token does not have the JSON I added:
Any idea?

Related

Adding nick field to registration new xmpp username using ejabberd

I wanted to send "nick" field from client to register new username with ejabberd in band registration. but Server is sending only username, password and instructions fields back to client to fill. I have checked below mod_register to modify these fields but none provide is available.
https://docs.ejabberd.im/admin/configuration/#mod-register
2018-05-29 23:01:08.426 [debug] <0.4613.3>#xmpp_socket:send:218 (tls|<0.4613.3>) Send XML on stream = <<"
<iq xml:lang='en' from='xmpp.test.in' type='result' id='mCbQBXKp-Sd4'>
<query xmlns='jabber:iq:register'>
<username/>
<password/>
<instructions>Choose a username and password to register with this server</instructions>
</query>
</iq>">>
Can any help me how to get nick included in registration itself?
If you are using Smack client for Android you can send additional attributes in createAccount method like:
public void signup(String user, String password, String nickname) throws SmackInvocationException {
connect();
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("name", nickname);
try {
AccountManager.getInstance(con).createAccount(user, password, attributes);
} catch (Exception e) {
throw new SmackInvocationException(e);
}
}
Another approach is to use Vcard with VcardManager and set nickname in smack like (after login or signup):
private Context context;
private XMPPConnection con;
public SmackVCardHelper(Context context, XMPPConnection con) {
this.context = context;
this.con = con;
}
public void save(String nickname) throws SmackInvocationException {
VCard vCard = VCardManager.getInstanceFor(connection).loadVCard();
try {
vCard.setNickName(nickname);
vCard.saveVCard(vcard);
} catch (Exception e) {
throw new SmackInvocationException(e);
}
}

How get token from auth facebook4j?

i will write my problem in this message and put link by exception (#number),i trying create web application that will from library facebook4j, I want get information about user account facebook and post information on facebook, in my code i can get json information about user or friends, but i get problem from token, when i work long time i get exception #1.
I'm generated this param setOAuthAccessToken() in graph api explorer copy and it paste in setOAuthAccessToken(). How right set and get token?
How create authentication in my web application via facebook4j?
Exception #1
FacebookException{
statusCode=400,
errorType='OAuthException',
errorMessage='Errorvalidatingaccesstoken: SessionhasexpiredonFriday,
25-Sep-1511: 00: 00PDT.ThecurrenttimeisFriday,
25-Sep-1513: 55: 17PDT.',
errorCode=190,
errorSubcode=463,
version=2.3.0
}
This is my code:
private final String TOKEN_VALUE = "CAACEdEose0cBAN5JHf6qs85DCcqKndE3N9XxjnMye3m7G7Re4VpSCqn4IzWXXoYeQe3QlUOH0NGucIWJbqfZBpFoHTUZA60YcZCZBwd4kCWD4g1qwZCyxy1ihpoiVuxZCV1u9ydjnhZCkNOoSqiqPpkzDWPfAc8ZBEDFtCvW78gZCbkZChrzfsMxpA3LZC08pZA5HrqaOe1BnrU1PiZAHJz4ZAEm3M";
private FacebookFactory facebookFactory;
private Facebook facebook;
private ConfigurationBuilder configurationBuilder;
private Configuration configuration;
public ConfigurationBuilder getConfigurationBuilder(){
configurationBuilder = new ConfigurationBuilder();
configurationBuilder.setDebugEnabled(true);
configurationBuilder.setOAuthAppId("746931638784611");
configurationBuilder.setOAuthAppSecret("07e2df67b4fe40e3f2051d79f40387c2");
configurationBuilder.setOAuthAccessToken(token);
configurationBuilder.setUseSSL(true);
configurationBuilder.setJSONStoreEnabled(true);
return configurationBuilder;
}
public Configuration getConfiguration(){
return getConfigurationBuilder().build();
}
public FacebookFactory getFacebookFactory(){
return new FacebookFactory(getConfiguration());
}
#Override
public String getFriends() {
facebook = getFacebookFactory().getInstance();
try {
ResponseList<Friend> friends = facebook.getFriends();
return friends.toString();
}catch (FacebookException e) {
e.printStackTrace();
}
return null;
}

Why HandshakeRequest doesn't return HttpSession in my ServerEndpointConfig.Configurator?

There is a good example for sharing HttpSession between Websocket and Rest service. (Spring DispatchServlet cannot find resource within Jetty) But it doesn't work for me. I'm not sure is there any thing I'm missing?
I'm using Jetty as websocket server and also I created a WebApp as well which injected by SpringConfig.
private void init() throws Exception
{
Server server = new Server();
// Create SSL Connector
ServerConnector serverConnector = getSSLConnector(server);
// Bundle to server
server.setConnectors(new Connector[] { serverConnector });
// Create request handler collection
HandlerCollection handlers = new HandlerCollection();
// Add WebSocket handler
final ServletContextHandler servletContextHandler = getWebSocketContextHandler();
handlers.addHandler(servletContextHandler);
// Add Servlet handler
handlers.addHandler(getWebAppServletContextHandler());
server.setHandler(handlers);
// Initial WebSocket
WebSocketServerContainerInitializer.configureContext(servletContextHandler);
// Start Jetty
server.start();
server.join();
}
Both WebSocket and Rest are working under same port perfectly, of course, with different context paths.
Now, I created a Rest service:
#RequestMapping(value = "/login", method = RequestMethod.POST)
#Consumes({ MediaType.APPLICATION_JSON_VALUE })
#Produces({ MediaType.APPLICATION_JSON_VALUE })
public #ResponseBody Message login(#RequestBody Credential credential, #Context HttpServletRequest servlerRequest)
{
...
HttpSession session = servlerRequest.getSession(true);
session.setAttribute("userName", credential.getUserName());
...
Message message = new Message();
...
return message;
}
In this service I created a HttpSession and stored something in. As I said, it works, and so does the session.
Rest client:
public void login() throws KeyManagementException, NoSuchAlgorithmException
{
final String loginServiceUri = HTTP_SERVICE_BASE_URI + "/login";
ClientConfig clientConfig = new DefaultClientConfig();
...
Client client = Client.create(clientConfig);
WebResource webResource = client.resource(loginServiceUri);
ClientResponse response = webResource
.type("application/json")
.post(ClientResponse.class, new Credential("user","pass"));
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
List<NewCookie>cookies = response.getCookies();
ClientEndpointConfigurator.setCookies(cookies); <== Store cookies as well as session to ClientEndpointConfigrator class
Message message = response.getEntity(Message.class);
...
}
ClientEndpointConfigrator class has a static list for all cookies which like this:
public class ClientEndpointConfigurator extends ClientEndpointConfig.Configurator {
private static List<NewCookie> cookies = null;
public static void setCookies(List<NewCookie> cookies) {
ClientEndpointConfigurator.cookies = cookies;
}
...
#Override
public void beforeRequest(Map<String, List<String>> headers) {
...
if(null != cookies)
{
List<String> cookieList = new ArrayList<String>();
for(NewCookie cookie: cookies)
{
cookieList.add(cookie.toString());
}
headers.put("Cookie", cookieList);
}
...
}
}
beforeRequest() method will put all cookies to request header. If you inspect the cookieList, you will see:
[JSESSIONID=tvum36z6j2bc1p9uf2gumxguh;Version=1;Path=/rs;Secure]
Things looks prefect.
Finally, create a server end ServerEndpointConfigurator class, and override the modifyHandshake() method to retrieve the session and cookies
public class SpringServerEndpointConfigurator extends ServerEndpointConfig.Configurator {
#Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
super.modifyHandshake(sec, request, response);
httpSession = (HttpSession)request.getHttpSession(); <== **It returns null here!**
...
}
}
}
I can't get my HttpSession back! and if you print headers out, you will see the cookie has been changed:
Cookie: JSESSIONID="tvum36z6j2bc1p9uf2gumxguh";$Path="/rs"
Any one knows what's the reason?
All right, I figured it out, it's because I put WebSocket and Rest to different context handler. Jetty keeps handlers isolate to each other. To share session information, you have to put them together.
But if someone does want to separate them, it is still possible done by sharing SessionManager or SessionHandler. There are many ways to achieve this, you can inject SessionHandler to each ServletContext or just define it as a static variable and put it on somewhere every one can reach, each way works.

How use SocialAuth with JSF to redirect?

I'm trying to use SocialAuth, the idea is very simple, click in log in with facebook then redirect the user to my website signed in.
The log in part I get it, which is below :
1) /index.xhtml
<h:form id="login-facebook">
<h:commandButton id="login" action="#{socialFacebook.login}" value="Login"/>
</h:form>
2) socialFacebook bean
package controller;
#ManagedBean(name="socialFacebook")
#RequestScoped
public class SocialFacebook implements Serializable{
private static final long serialVersionUID = -4787254243136316495L;
private String code;
#PostConstruct
public void init(){
try {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
SocialAuthManager manager = (SocialAuthManager)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("authManager");
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(request);
AuthProvider provider = manager.connect(paramsMap);
// get profile
Profile p = provider.getUserProfile();
System.out.println(p.getFullName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void login(){
try {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
//Create an instance of SocialAuthConfig object
SocialAuthConfig config = SocialAuthConfig.getDefault();
//load configuration. By default load the configuration from oauth_consumer.properties.
//You can also pass input stream, properties object or properties file name.
config.load();
//Create an instance of SocialAuthManager and set config
SocialAuthManager manager = new SocialAuthManager();
manager.setSocialAuthConfig(config);
//URL of YOUR application which will be called after authentication
//String successUrl = "http://localhost:8080/cc/pages/system/login_facebook.xhtml" + ";jsessionid=" + req.getSession().getId();
String successUrl = "http://localhost:8080/cc/pages/system/index.xhtml" + ";jsessionid=" + request.getSession().getId();
// get Provider URL to which you should redirect for authentication.
// id can have values "facebook", "twitter", "yahoo" etc. or the OpenID URL
String url = manager.getAuthenticationUrl("facebook", successUrl);
// Store in session
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("authManager", manager);
//redirect to the successful login page
FacesContext.getCurrentInstance().responseComplete();
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
3) Facebook returned the following URL:
http://localhost:8080/cc/pages/system/home_facebook.xhtml;jsessionid=e143aa975fa3f313c677fbcb03e3?code=AQAmJXdQX0B__zJHXnRyPfgaG1CfNUEEEEEEEEEEEEEEEZJLEpsT5s1spd3KtWGWI2HYaIOZKLkrn8axKs4iKwJVQJwJQB_WSs2iWkp2DDDDDDDDDDDDtdRPLPG7psp6r2PYmn7CTm2QNNha7f1QlgmoZtBsIEF0SSSSSSSSSSSSSSSSSSSSSSS8RutAU8dqI2KDE57f#_=_
4) It pass by my init method as BalusC suggest but always prints nope :( :
#ManagedBean(name="redirectFacebook")
#RequestScoped
public class RedirectFacebook implements Serializable{
private static final long serialVersionUID = -566276017320074630L;
private String code;
private Profile profile;
#PostConstruct
public void init(){
try {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession session = (HttpSession) request.getAttribute("jsessionid");
if (request.getAttribute("code") != null)
System.out.println("code");
else
System.out.println("nope :(");
if (session != null){
SocialAuthManager manager = (SocialAuthManager)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("authManager");
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(request);
AuthProvider provider = manager.connect(paramsMap);
// get profile
profile = provider.getUserProfile();
System.out.println(profile.getFullName());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
5) And it prints nope :( too in my home_facebook page:
<h:form id="redirect-facebook-form">
<f:metadata>
<f:viewParam name="code" value="#{redirectFacebook.code}" />
</f:metadata>
<h:panelGroup rendered="#{not empty redirectFacebook.profile}">
Hello, you're successfully associated as #{socialFacebook.profile.firstName} on Facebook
</h:panelGroup>
<h:panelGroup rendered="#{empty redirectFacebook.profile}">
Nope :(
</h:panelGroup>
</h:form>
But, I'm a bit confuse how to get the result in my bean and do some verifications as if the user is registered or not for instance. I know, looking some code in Google, that I have to do this, but how can I redirect to my bean and do this and redirect the user to the proper page ?
SocialAuthManager manager = (SocialAuthManager)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("authManager");
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(request);
AuthProvider provider = manager.connect(paramsMap);
// get profile
Profile p;
p = provider.getUserProfile();
This is really taking some nights to figure it out.
Any idea is very appreaciated, thanks.
I don't see any code level issue except you are using localhost in URL.
Here is a wiki link which describes how to run application with localhost.
Please let me know if this does not work.

Generating random session id whenever user uses login() in web services

Am new to web services. Am trying to generate unique session id for every login that a user does, in web services.
What I thought of doing is,
Write a java file which has the login and logout method.
Generate WSDL file for it.
Then generate web service client(using Eclipse IDE), with the WSDl file which I generate.
Use the generated package(client stub) and call the methods.
Please let me know if there are any flaws in my way of implementation.
1. Java file with the needed methods
public String login(String userID, String password) {
if (userID.equalsIgnoreCase("sadmin")
&& password.equalsIgnoreCase("sadmin")) {
System.out.println("Valid user");
sid = generateUUID(userID);
} else {
System.out.println("Auth failed");
}
return sid;
}
private String generateUUID(String userID) {
UUID uuID = UUID.randomUUID();
sid = uuID.toString();
userSessionHashMap = new HashMap<String, String>();
userSessionHashMap.put(userID, sid);
return sid;
}
public void logout(String userID) {
Set<String> userIDSet = userSessionHashMap.keySet();
Iterator<String> iterator = userIDSet.iterator();
if (iterator.equals(userID)) {
userSessionHashMap.remove(userID);
}
}
2. Generated WSDL file
Developed the web service client from the wsdl.
4. Using the developed client stub.
public static void main(String[] args) throws Exception {
ClientWebServiceLogin objClientWebServiceLogin = new ClientWebServiceLogin();
objClientWebServiceLogin.invokeLogin();
}
public void invokeLogin() throws Exception {
String endpoint = "http://schemas.xmlsoap.org/wsdl/";
String username = "sadmin";
String password = "sadmin";
String targetNamespace = "http://WebServiceLogin";
try {
WebServiceLoginLocator objWebServiceLoginLocator = new WebServiceLoginLocator();
java.net.URL url = new java.net.URL(endpoint);
Iterator ports = objWebServiceLoginLocator.getPorts();
while (ports.hasNext())
System.out.println("ports Iterator size-->" + ports.next());
WebServiceLoginPortType objWebServiceLoginPortType = objWebServiceLoginLocator
.getWebServiceLoginHttpSoap11Endpoint();
String sid = objWebServiceLoginPortType.login(username, password);
System.out.println("sid--->" + sid);
} catch (Exception exception) {
System.out.println("AxisFault at creating objWebServiceLoginStub"
+ exception);
exception.printStackTrace();
}
}
On running the this file, I get the following error.
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: java.net.ConnectException: Connection refused: connect
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:java.net.ConnectException: Connection refused: connect
Can anyone suggest an alternate way of handling this task ? And what could probably be the reason for this error.
Web services are supposed to be stateless, so having "login" and "logout" web service methods doesn't make much sense.
If you want to secure web services calls unfortunately you have to code security into every call. In your case, this means passing the userId and password to every method.
Or consider adding a custom handler for security. Read more about handlers here.